The thread pool

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

Definitions and methods

The work of the thread pool controls the number of threads running, puts tasks into queues during processing, and then starts these tasks after the thread is created. If the number of threads exceeds the maximum number, the exceeding number of threads queue up to wait for other threads to complete their execution, and then take the task out of the queue to execute.

Features:

Thread reuse, control the maximum number of concurrent, management threads.

Benefits:

  1. Reduce resource consumption. Reduce the cost of thread creation and destruction by reusing created threads.
  2. Improve response speed. When a task arrives, it executes immediately without waiting for a thread to be created
  3. Improve thread manageability. When threads are scarce resources, if created without limit, they will not only consume system resources, but also reduce system stability. Thread pools can be used for uniform allocation, tuning, and monitoring.

Simple architecture diagram:

We are using ThreadPoolExecutor.

Alibaba Development Specification Manual:

【 Mandatory 】 Thread pools cannot be created by Executors. Use ThreadPoolExecutor to clear the running rules of the thread pool and avoid resource depletion.

* If the thread pool object returns by Executors, it has the following disadvantages:

1) FixedThreadPool and SingleThreadPool

The allowed queue length is integer. MAX_VALUE, which may accumulate a large number of requests and result in OOM.

2) CachedThreadPool:

The number of threads allowed to be created is integer.max_value, which may create a large number of threads, resulting in OOM.

First use the Following tools to create the thread pool:

A FixedThreadPool is called a reusable thread pool with a fixed number of threads.

public class demo1 {
    public static void main(String[] args) {
        // Use the Executors tool class to create the newFixedThreadPool thread pool
        ExecutorService executor = Executors.newFixedThreadPool(3);
​
        try{
            for (int i = 0; i < 10; i++) {
                executor.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"Mission execution"); }); }}finally{ executor.shutdown(); }}}Copy the code

SingleThreadExecutor is an Executor that uses a single worker thread, eliminating resource consumption when creating and destroying threads.

public class demo1 {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        try{
            for (int i = 0; i < 10; i++) {
                executor.execute(()->{
​
                    System.out.println(Thread.currentThread().getName()+"\t Task Execution"); }); }}finally{ executor.shutdown(); }}}Copy the code

CachedThreadPool is a thread pool that creates new threads as needed. Expandable thread pool.

public class demo1 {
    public static void main(String[] args) {
        // Use the Executors tool class to create the newFixedThreadPool thread pool
        //ExecutorService executor = Executors.newFixedThreadPool(3);
        // One thread pool is one thread
        //ExecutorService executor = Executors.newSingleThreadExecutor();
        ExecutorService executor = Executors.newCachedThreadPool();
        try{
            for (int i = 0; i < 10; i++) {
                executor.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"\t Task Execution"); }); }}finally{ executor.shutdown(); }}}Copy the code
Pool-1 thread-2 Tasks Pool-1 thread-1 tasks Pool-1 thread-4 tasks Pool-1 thread-3 tasks Pool-1 thread-5 Tasks Pool-1 thread-6 tasks Task execution Pool-1-thread-7 task execution pool-1-thread-8 Task execution pool-1-thread-9 Task execution Pool-1-thread-10 Task executionCopy the code

The process of using thread pools when setting up deferred operations to mimic time-consuming code.

package com.JucPool;
​
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
​
/** * The basics and three main methods of thread pooling */
public class demo1 {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        try{
            for (int i = 0; i < 10; i++) {
                // Pause for a few seconds
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                executor.execute(()->{
                    System.out.println(Thread.currentThread().getName()+"\t Task Execution"); }); }}finally{ executor.shutdown(); }}}Copy the code
Pool-1-thread-1 tasks Pool-1-thread-1 tasks Pool-1-thread-1 tasks Pool-1-thread-1 tasks Pool-1-thread-1 tasks Task Execution Pool-1 thread-1 task Execution pool-1 thread-1 task Execution Pool-1 thread-1 task Execution Process finished with exit code 0Copy the code

This drops to the SingleThreadExecutor thread pool.

Simple source code analysis

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

By comparison, ThreadPoolExecutor is used to implement the underlying implementation, but the parameters passed are also related to the blocking queue.

Parameters :(very important)

  1. ·corePool: Size of thread pool resident core thread pool.
  2. ·maximumPool: Maximum thread pool size — the maximum number of threads in a thread pool that can be executed simultaneously
  3. KeepAliveTime: The keepAliveTime for the remaining idle threads in the corePool. When the number of threads in the pool exceeds the number of threads in the corePool and the number of idle threads reaches keepAliveTime, the remaining threads are destroyed until there are only corePool threads left
  4. Unit – keepAliveTime Time unit of the keepAliveTime parameter
  5. WorkQueue – A queue used to save tasks before they are executed. This queue will only hold Runnable tasks submitted by the execute method.

There are also two arguments in ThreadPoolExecutor:

  1. ThreadFactory: represents the ThreadFactory that generates worker threads in the thread pool and is used to create threads, generally by default
  2. Handler: A runnable policy for refusing requests when the queue is full and the number of working threads exceeds the maximum thread pool size

This is an important summary of the seven parameters in the thread pool, and the thread pool execution flow will be analyzed later in terms of what happens when a reject policy is implemented.