“This is the 15th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

ThreadPoolExecutor Important parameters

ThreadPoolExecutor has several important member variables: keepAliveTime, allowCoreThreadTimeOut, poolSize, corePoolSize, maximumPoolSize. The following are introduced respectively:

  • CorePoolSize: The base size of the thread pool. The basic size is explained below.

  • MaximumPoolSize: maximum number of threads allowed in the thread pool.

    Note that there is also largestPoolSize, which records the maximum number of threads that have ever occurred. Because setMaximumPoolSize() can change the maximum number of threads.

  • PoolSize: specifies the number of current threads in the thread pool.

  • AllowCoreThreadTimeOut: Whether to allow the core thread to exit due to timeout.

    If this value is false and poolSize<=corePoolSize, the thread pool guarantees that the core threads are alive and will not timeout out.

    If true, the timeout exit is allowed regardless of poolSize.

    If poolSize>corePoolSize, this parameter, whether true or false, allows timeout.

    Relevant judgments are as follows:

    (poolSize > corePoolSize || allowCoreThreadTimeOut)
    Copy the code
  • KeepAliveTime: If a thread stays idle for longer than this value, it will exit due to timeout. Whether to allow timeout exits depends on the logic above.

PoolSize, corePoolSize, maximumPoolSize

PoolSize, corePoolSize, maximumPoolSize

When a new task is submitted:

  1. ifpoolSize<corePoolSizeA new thread is added to handle the new task.
  2. ifpoolSize=corePoolSizeNew tasks are put into a blocking queue to wait.
  3. If the capacity of the blocking queue reaches its upper limit, andpoolSize<maximumPoolSizeNew threads are added to process tasks.
  4. If the blocking queue is full andpoolSize=maximumPoolSize, the thread pool has reached its limit and will reject new tasks according to saturation policy RejectedExecutionHandler.

CorePoolSize <=maximumPoolSize, poolSize<=maximumPoolSize; PoolSize is not comparable to corePoolSize. PoolSize can be larger than corePoolSize.

Four thread pools

Executors provides four thread pools:

  • NewCachedThreadPool: Cache thread pool. If the length of the thread pool exceeds the processing requirement, idle threads can be reclaimed. If none are reclaimed, new threads can be created.
  • NewFixedThreadPool: a fixed-length thread pool that controls the maximum number of concurrent threads, and the excess threads wait in the queue.
  • NewScheduledThreadPool: Scheduled thread pool that supports scheduled and periodic task execution.
  • NewSingleThreadExecutor: single-threaded thread pool that uses a unique thread to execute tasks, ensuring that all tasks are executed in the specified order (FIFO, LIFO, priority).

CorePoolSize and maximumPoolSize are available in each thread pool.

Through several newXXX function source can be known, the source code is as follows:

newFixedThreadPool

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}
Copy the code

The corePoolSize and maximumPoolSize of a fixed-length thread pool are the same. It’s all set points.

newCachedThreadPool

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

CorePoolSize is 0, maximumPoolSize is int maximum.

newSingleThreadExecutor

public static ExecutorService newSingleThreadExecutor(a) {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1.1.0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
Copy the code

Single-threaded thread pools corePoolSize and maximumPoolSize are both 1.

newScheduledThreadPool

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE,
          DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
          new DelayedWorkQueue());
}
Copy the code

The scheduled thread pool uses a subclass of ThreadPoolExecutor, and you can see that corePoolSize is defined and maximumPoolSize is int maximum.

Note that corePoolSize and maximumPoolSize are not final because setCorePoolSize and setMaximumPoolSize() can be changed.

Blocking queue

What is the saturation value of the blocking queue mentioned above?

You can see this in the code above

The default size of LinkedBlockingQueue is the maximum size of int, as shown below:

public LinkedBlockingQueue(a) {
    this(Integer.MAX_VALUE);
}
Copy the code

(2) The scheduled thread pool uses the DelayedWordQueue, which defaults to 16, but can grow dynamically, and the maximum value is the maximum value of int, as follows:

private static final int INITIAL_CAPACITY = 16;
privateRunnableScheduledFuture<? >[] queue =newRunnableScheduledFuture<? >[INITIAL_CAPACITY];private void grow(a) {
    int oldCapacity = queue.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1); // grow 50%
    if (newCapacity < 0) // overflow
        newCapacity = Integer.MAX_VALUE;
    queue = Arrays.copyOf(queue, newCapacity);
}
Copy the code

SynchronousQueue is used for the cache thread pool, which has no saturation value, and corePoolSize is 0 by default. So it creates a new thread that has to do with the SynchronousQueue mechanism, which I won’t go into here, but if you’re interested you can explore this class.

Pay attention to the public number: BennuCTech, get more dry goods!