Thread pool basics

1. Thread pool Executors: The ThreadPoolExecutor class implements the Executor interface, so that any Runnable object can be scheduled by the ThreadPoolExecutor thread pool through this interface. Common thread pool types

  • public static ExecutorService newFixedThreadPool(int nThreads)
    Copy the code

    Returns a thread pool with a fixed number of threads. The number of threads is always the same. Execute immediately when there are idle threads. If not, the new thread exists in a task queue temporarily. When the thread is idle, it starts to process tasks in the task queue.

  • public static ExecutorService newSingleThreadExecutor(a)
    Copy the code

    Returns a thread pool with only one thread. The new line is stored in the task queue. When the thread is idle, the task in the task queue is processed.

  • public static ExecutorService newCachedThreadPool(a)
    Copy the code

    Returns a thread pool that can adjust the number of threads as needed. The number of processes in a thread is uncertain, but if there are idle threads that can be reused, that thread will be used first. If all threads are working and a new task is submitted, a new thread is created to execute the task. All threads will return to the thread pool for feeding after the current task is complete.

  • public static ScheduledExecutorService newSingleThreadScheduldExecutor(a)
    Copy the code

    Return a ScheduledExecutorService object with a thread pool size of 1. Execute after a fixed delay, or execute a task periodically

  • public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
    Copy the code

    Same as above, but you can specify the number of threads.


Internal implementation of the core thread pool

For several thread pools in the core, the internal implementation uses the ThreadPoolExecutor implementation.

  • public static ExecutorService newFixedThreaPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads,nThreads,
                                     0L,TimeUnit.SECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    Copy the code
  • public static ExecutorService newSingleThreadExecutor(a) {
        return new ThreadPoolExecutor(1.1.0L,TimeUnit.SECONDS,
                                     new LinkedBlockingQueue<Runnable>());
    }
    Copy the code
  • public static ExecutorService newCachedThreadPool(a) {
        return new ThreadPoolExecutor(0,Integer.MAX_VALUE,
                                     60L,TimeUnit.SECONDS,
                                     new SynchronousQueue<Runnable>());
    }
    Copy the code

Take a look at the most important constructor of ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long KeepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)
Copy the code

The parameters of the function are as follows:

  • corePoolSize: Number of threads in the thread pool.
  • maximumPoolSize: Maximum number of threads in the thread pool.
  • keepAliveTime: When the number of thread pools exceedscorePoolSize, the lifetime of the excess idle threads.
  • unit:keepAliveTimeOf the unit.
  • workQueue: task queue, tasks that have been submitted but not yet executed.
  • threadFactory: thread factory, used to create threads, usually using the default.
  • handler: Rejection policy. How to say no to tasks when there are too many to handle.

In the above parameters, the rest is easy to understand, but the workQueue and handler need to be mentioned.


workQueueTask queue explanation

A workQueue is a queue of submitted tasks that have not yet been executed. It is an object of the BlockingQueue interface that exists only for Runnable objects. The following blockingQueues can be used in the constructor of ThreadPoolExecutor, depending on the queue functionality:

  • Queue for direct submissionSynchronousQueue:SychronousQueueIs a special oneBlockingQueue.SychronousQueueWithout capacity, each insert waits for a corresponding delete, and conversely, each delete waits for a corresponding insert. If you are usingSychronousQueueIf there are no idle threads, try to create a new thread. If the number of processes has reached the maximum, the policy will be rejected. Therefore, useSychronousQueueIt’s usually very largemaximumcorePoolSizeOtherwise, it is easy to implement a rejection strategy.
  • A bounded task queueArrayBlockingQueueFeatures:If a new task needs to be executed, if the actual thread pool is less thancorePoolSize, the new thread will be created first. If more thancorePoolSize, the new task is added to the waiting queue. If the wait queue is full and unable to join, the bus maturity is not greater thanmaximumPoolSizeCreate a new thread to execute the task. If yes, the denial policy is executed.
  • Unbounded queue of tasksLinkedBlockingQueueFeatures:If a new task needs to be executed, if the actual thread pool is less thancorePoolSize, the new thread will be created first. If more thancorePoolSizeTo enter the waiting queue.
  • Priority task queuePriorityBlockingQueue: Tasks can be executed according to their priorities.

handlerRejection Strategy Explanation

The built-in rejection policies of JKD are implemented through the RejectedExecutionHandler interface, as follows:

  • AbortPolicyStrategy: Directly throw exceptions to prevent the system from working properly;
  • CallerRunsPolicyPolicy: Run the currently discarded task directly in the caller thread as long as the thread is not closed.Warning: Performance may deteriorate sharply
  • DiscardOledstPolicyStrategy: Discard one of the oldest requests and try to submit the current task again.
  • DiscardPolicyPolicy: Discard unprocessed requests, do not process them, and do not prompt them.