Grilled vernacular deep JAVA thread pool - the little sister to the programmer implements a thread pool she was ......

Written on the front

Thread pool is interviewing high-frequency test sites, this is what as entrance, vernacular to explain the execution thread pool, thread pool to determine the source Pa choice, then two combat the thread pool created and select RejectedExecutionHandler saturated reject policy from the thread pool.

Introduction thread pool

Use Background:

  • When we have a lot of code to use multiple threads to execute in the project
  • When the computer cpu hardware resources alone will not create the destruction of multiple threads at the same time

Thread Pool appearances:

  • For example, a thread pool to save money on the bank counter understandable: people want to go to the bank like a thread counters for businesses to save money, but the thread pool is the bank counter window, but a bank can not be just a window, the window number is window is determined by the leadership of the bank (which is like the thread pool maximumPoolSize parameters), in which the bank clerk on duty every day is also determined by the leadership, so the opening is limited (corePoolSize parameter which is like the thread pool).

Why use a thread pool instead of directly creating a thread:

  • In accordance with the above example cited, then create a thread to execute the code directly like someone wants to apply for banking, Bank flew to arrange for a salesman to give him to do, then multiply the number once the deal with a limited number of sales is insufficient business process for each person, so open a bank, sooner or later get cold.
  • And with the thread pool is like to do business, but many people counter is full of windows of other customers to wait in front of complete business process, whose turn it is to conduct business who will be able to apply, a salesman will be able to handle more business, so to undertake unlimited business (customers) with limited resources (clerk).

Select the reason for the thread pool

The JDK provides:

  • FixedThreadPool
  • CachedThreadPool (elastic caching thread pool)
  • SingleThreadPool (single-threaded thread pool)
  • ScheduledThreadpool (timer thread pool)
  • Four kinds of thread pool, but not easy to use, I analyzed by specific source.

FixedThreadPool

  • Executors.java
    -newFixedThreadPool()方法
   /**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue.  At any point, at most
     * {@code nThreads} threads will be active processing tasks.
     * If additional tasks are submitted when all threads are active,
     * they will wait in the queue until a thread is available.
     * If any thread terminates due to a failure during execution
     * prior to shutdown, a new one will take its place if needed to
     * execute subsequent tasks.  The threads in the pool will exist
     * until it is explicitly {@link ExecutorService#shutdown shutdown}.
     *
     * @param nThreads the number of threads in the pool
     * @return the newly created thread pool
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

You can see the way to create a FixedThreadPool returned to LinkedBlockingQueue () as the waiting queue thread pool, so we follow up LinkedBlockingQueue.

  • LinkedBlockingQueue.java
//这是LinkedBlockingQueue的插入方法,可以看到只要线程数少于capacity这个变量那么都可以进入队列,这时我们找到这个变量的具体数字为多少
    public boolean offer(E e) {
        if (e == null) throw new NullPointerException();
        final AtomicInteger count = this.count;
        if (count.get() == capacity)
            return false;
        int c = -1;
        Node<E> node = new Node<E>(e);
        final ReentrantLock putLock = this.putLock;
        putLock.lock();
        try {
            if (count.get() < capacity) {
                enqueue(node);
                c = count.getAndIncrement();
                if (c + 1 < capacity)
                    notFull.signal();
            }
        } finally {
            putLock.unlock();
        }
        if (c == 0)
            signalNotEmpty();
        return c >= 0;
    }
==================================================================
可以见到这个数字的最大值是int的最大值
================================================================
 /** The capacity bound, or Integer.MAX_VALUE if none */
    private final int capacity;

According to the code it can be seen that if the use of this thread pool, then almost to a thread queue allows to enter the queue, it will accumulate a lot of requests.

SingleThreadPool
this thread pool wait queue and FixedThreadPool as the section FixedThreadPool resolution.

CachedThreadPool和ScheduledThreadpool

 public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
=========================================================================
      public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
       
    }
    }
    }

The maximum number of threads in the thread pool allows the creation of these two is Integer.MAX_VALUE, then this will lead to OOM.

Thread pool execution process

Thread Pool
The first step will be receiving a code based on the work of drawing, thread pool and thread pool threads allocated to execute the code, then
1. If maximumPoolSize> number of requests> corePoolSize thread pool threads to create code that calls
2. If the number of requests> maximumPoolSize then the request will be put into a waiting queue BlockingQueue
3. If the request continues to accumulate until the request queue is full in the waiting queue and thread pool is still no idle thread
then it causes a thread pool saturation denial strategy: RejectedExecutionHandler, the default is AbortPolicy ( Throw an exception)

Four saturation refused policy resolution

1, AbortPolicy: direct throw an exception

2, CallerRunsPolicy: only thread running task calls where

3, DiscardOldestPolicy: discard queue recent task and execute the current task.

4, DiscardPolicy: no treatment, discarded.

Real 1: Implementing a thread pool

In the production of the best is his call to create a thread pool ThreadPoolExecutor

/*创建一个线程池
*
*  corePoolSize(线程池的基本大小):当提交一个任务到线程池时,线程池会创建一个线程来执行任务,即使其他空闲的基本线程能够执行新任务也会创建线程,
* 等到需要执行的任务数大于线程池基本大小时就不再创建。如果调用了线程池的prestartAllCoreThreads方法,线程池会提前创建并启动所有基本线程。
    runnableTaskQueue(任务队列):用于保存等待执行的任务的阻塞队列。 可以选择以下几个阻塞队列。
       maximumPoolSize(线程池最大大小):线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,4
    则线程池会再创建新的线程执行任务。值得注意的是如果使用了无界的任务队列这个参数就没什么效果。

·        ThreadFactory:用于设置创建线程的工厂,可以通过线程工厂给每个创建出来的线程设置更有意义的名字。

·        RejectedExecutionHandler(饱和策略):当队列和线程池都满了,说明线程池处于饱和状态,
        那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。以下是JDK1.5提供的四种策略。

     keepAliveTime(线程活动保持时间):线程池的工作线程空闲后,保持存活的时间。所以如果任务很多
        并且每个任务执行的时间比较短,可以调大这个时间,提高线程的利用率。

·        TimeUnit(线程活动保持时间的单位):可选的单位有天(DAYS),小时(HOURS),分钟(MINUTES),秒(SECONDS),毫秒(MILLISECONDS),微秒(MICROSECONDS, 千分之一毫秒)和毫微秒(NANOSECONDS, 千分之一微秒)。

* */
public class threadPoolDemo {
    static int maxNumberOfThreadPool=3;
    public static void main(String[] args)  {
        ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(2,3,1L,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(2),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
        //这里设置成6个任务需要线程池执行
        //但是线程池最大为3 且阻塞队列最大为2 所以线程池就会拒绝
        for (int i = 0; i <=5 ; i++) {
            System.out.println("线程\t"+i+"\t正在提交到线程池中执行");
            try{
                threadPoolExecutor.execute(new ThreadDemo("工作"+(i+1)));
            }
            catch (Exception e)
            {
//                threadPoolExecutor.
                try {
                    threadPoolExecutor.awaitTermination(3,TimeUnit.SECONDS);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                e.printStackTrace();
                    System.out.println(Thread.currentThread().getName()+"\t"+"线程池因为没有空余线程以及阻塞队列也满了所以"+"工作"+(i+1)+"拒绝执行");
            }
        }
        threadPoolExecutor.shutdown();
    }
}

class  ThreadDemo implements  Runnable
{
    String threadName=null;
    public ThreadDemo(String threadName) {
        this.threadName = threadName;
    }
    @Override
    public void run() {
        System.out.println(threadName+"被\t"+Thread.currentThread().getName()+"\t执行了");
       try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(threadName+"\t执行完毕");
    }
}

======================================================================
运行结果:
*线程	0	正在提交到线程池中执行
线程	1	正在提交到线程池中执行
线程	2	正在提交到线程池中执行
线程	3	正在提交到线程池中执行
线程	4	正在提交到线程池中执行
工作1被	pool-1-thread-1	执行了
线程	5	正在提交到线程池中执行
工作2被	pool-1-thread-2	执行了
工作5被	pool-1-thread-3	执行了
工作2	执行完毕
工作5	执行完毕
工作1	执行完毕
工作3被	pool-1-thread-3	执行了
工作4被	pool-1-thread-2	执行了
**********************************************************
main	线程池因为没有空余线程以及阻塞队列也满了所以工作6拒绝执行
java.util.concurrent.RejectedExecutionException: Task ThreadPool.ThreadDemo@5caf905d rejected from java.util.concurrent.ThreadPoolExecutor@27716f4[Running, pool size = 3, active threads = 3, queued tasks = 2, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
	at ThreadPool.threadPoolDemo.main(threadPoolDemo.java:39)
********************************************************
工作4	执行完毕
工作3	执行完毕

As can be seen from the results of a default policy is thrown.

Combat 2: RejectedExecutionHandler saturated reject selection policy

new ThreadPoolExecutor.DiscardPolicy()

ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor
(2,3,1L,TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy());

运行结果:
* 线程	0	正在提交到线程池中执行
线程	1	正在提交到线程池中执行
线程	2	正在提交到线程池中执行
线程	3	正在提交到线程池中执行
线程	4	正在提交到线程池中执行
工作1被	pool-1-thread-1	执行了
工作2被	pool-1-thread-2	执行了
线程	5	正在提交到线程池中执行
工作5被	pool-1-thread-3	执行了
工作1	执行完毕
工作2	执行完毕
工作3被	pool-1-thread-2	执行了
工作4被	pool-1-thread-1	执行了
工作5	执行完毕
工作4	执行完毕
工作3	执行完毕

6 you can see the work because there is no idle thread in the thread pool and the queue is full so be discarded in accordance with RejectedExecutionHandler strategy.

new ThreadPoolExecutor.DiscardOldestPolicy()

ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor
(2,3,1L,TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(2),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy());


该策略是丢弃在队列种等待最久的线程并将此线程再次提交
线程	0	正在提交到线程池中执行
线程	1	正在提交到线程池中执行
线程	2	正在提交到线程池中执行
线程	3	正在提交到线程池中执行
工作1被	pool-1-thread-1	执行了
线程	4	正在提交到线程池中执行
工作2被	pool-1-thread-2	执行了
线程	5	正在提交到线程池中执行
工作5被	pool-1-thread-3	执行了

工作5	执行完毕
工作2	执行完毕
工作1	执行完毕
工作4被	pool-1-thread-3	执行了
工作6被	pool-1-thread-1	执行了

工作6	执行完毕
工作4	执行完毕
*********************************
* 线程3被丢弃了 因为选用了等待时间长就丢弃的饱和拒绝策略
* **********************************
    

new ThreadPoolExecutor.CallerRunsPolicy()

ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor
(2,3,1L,TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(2),
Executors.defaultThreadFactory(),
new new ThreadPoolExecutor.CallerRunsPolicy());


线程	0	正在提交到线程池中执行
线程	1	正在提交到线程池中执行
线程	2	正在提交到线程池中执行
线程	3	正在提交到线程池中执行
工作1被	pool-1-thread-1	执行了
线程	4	正在提交到线程池中执行
工作2被	pool-1-thread-2	执行了
线程	5	正在提交到线程池中执行
***************************
工作6被	main	执行了
*****************************
工作5被	pool-1-thread-3	执行了
工作6	执行完毕
工作5	执行完毕
工作2	执行完毕
工作1	执行完毕
工作3被	pool-1-thread-3	执行了
工作4被	pool-1-thread-1	执行了
工作4	执行完毕
工作3	执行完毕
    

Guess you like

Origin blog.csdn.net/qq_38404698/article/details/93612147