[Java|Multithreading and high concurrency] Detailed explanation of thread pool


insert image description here

1. Introduction to thread pool

The Java thread pool is a mechanism for managing and reusing threads. It can obtain threads from the thread pool when tasks need to be performed, perform tasks, and then put the threads back into the pool for subsequent use. The thread pool can effectively manage the number of threads and improve program performance and resource utilization.

Why is it faster to take threads from the thread pool than to create threads directly?

Creating a thread is done in the operating system kernel, which involves switching from "user mode" to "kernel mode". This switch has a certain overhead. The thread pool thread is a pure user mode implementation.

2. Create a thread pool

Note the way the thread pool is created here:

ExecutorService executorService = Executors.newCachedThreadPool();

There is no new here, but it is created through Executorsthe static method , which involves a design pattern - "factory pattern"newCachedThreadPool

3. Introduction to factory pattern

The Factory Pattern (Factory Pattern) is a design pattern for creating objects, which provides a way to encapsulate the object creation process, decoupling the client code from the instantiation process of specific objects.

The main purpose of the factory pattern is to create objects through a factory class, rather than using keywords directly in client code newto instantiate objects. This hides the details of the creation of specific objects, providing a more flexible and extensible design.

For details, please refer to: Factory Mode | Rookie Tutorial

4. Use of thread pool

The use of the thread pool is very simple, just need to implement submitthe method

public class Demo19 {
    
    
    public static void main(String[] args) {
    
    
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("线程执行的任务1");
            }
        });
        executorService.submit(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("线程执行的任务2");
            }
        });
        executorService.submit(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("线程执行的任务3");
            }
        });
    }
}

The main thing here is to put the tasks in the thread pool, and the threads in the thread pool will execute these tasks

operation result:

insert image description here

5. Implement thread pool

To implement a thread pool, you must first figure out what functions the thread pool has.

A thread pool can submit N tasks at the same time, and there are M threads in the thread pool to execute the N tasks

How to assign N tasks to M threads?

This problem can be solved using the producer-consumer model.

The following is a simple implementation of a thread pool:

public class MyThreadPool {
    
    
    private BlockingQueue<Runnable> blockingQueue = new public class MyThreadPool {
    
    
    private BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<>();

    public void submit(Runnable runnable) throws InterruptedException {
    
    
        // 将任务添加到阻塞队列中
        blockingQueue.put(runnable);
    }

    public MyThreadPool(int m){
    
    
        // 创建m个线程
        for (int i = 0; i < m; i++) {
    
    
            Thread t = new Thread(() ->{
    
    
                // 让它一直扫描阻塞队列
                while (true) {
    
    
                    try {
    
    
                        // 取出任务,并执行
                        Runnable runnable = blockingQueue.take();
                        runnable.run();
                    } catch (InterruptedException e) {
    
    
                        throw new RuntimeException(e);
                    }
                }
            });
            t.start();
        }
    }
}

Test the above code:

public class Demo20 {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        MyThreadPool pool = new MyThreadPool(5);
        for (int i = 0; i < 10; i++) {
    
    
            int temp = i;
            pool.submit(new Runnable() {
    
    
                @Override
                public void run() {
    
    
                    System.out.println("任务"+ temp);
                }
            });
        }
    }
}

operation result:

insert image description here

However, the number of threads created in the above code is "fixed" and can be adjusted as needed

6. Explanation of the construction method of ThreadPoolExecutor

ThreadPoolExecutorIt is a concrete implementation class of the thread pool in Java, which 实现implements the ExecutorService interface. ExecutorService is an advanced thread pool management interface that provides more flexibility and functionality.

ThreadPoolExecutorThe construction method of this class is more complicated
insert image description here

parameter:

  • corePoolSize- the number of threads to keep in the pool even when idle, unless setallowCoreThreadTimeOut

  • maximumPoolSize- the maximum number of threads allowed in the pool

  • keepAliveTime等待新任务- When the number of threads is greater than cores, this is the maximum time that excess idle threads will be before terminating .

  • unit- keepAliveTimethe time unit of the argument

  • workQueue- Queues for use before executing tasks. This queue will only hold tasks executesubmitted by the method Runnable. (The task queue passed in by yourself, if passed, use the passed queue. If not passed, the thread pool will be created)

  • threadFactory- The factory to use when the executor creates new threads

  • handler- Handler to use when task execution is rejected because thread limit and queue capacity are reached

The following four procedures are used when task execution is rejected:

insert image description here

In actual development, the rejection strategy here is mainly selected according to the requirements for processing.

7. How to determine the number of threads in the thread pool?

The thread pool can customize the number of threads

So in actual development, what is the appropriate number of threads in the thread pool?

This question mainly depends on the following points:

  1. Task type: Different types of tasks have different requirements for the number of threads. If it is a CPU-intensive task, usually the number of threads should be similar to the number of CPU cores to make full use of CPU resources. If it is an IO-intensive task, you can set a larger number of threads to handle concurrent IO operations.
  2. System resources: The hardware resources and performance of the system need to be considered. If the system resources are limited, such as memory, CPU, etc., the number of threads should be properly controlled to avoid resource competition and performance degradation caused by too many threads.
  3. Concurrency: The number of threads needs to be determined according to the concurrency of tasks. If the task concurrency is high, you can increase the number of threads to improve task processing capabilities. If the task concurrency is low, the number of threads can be reduced to save resources.
  4. Response time: Response time requirements of tasks need to be considered. If the task needs to respond quickly, the number of threads can be increased to reduce the waiting time. If the task's response time can accept a long delay, you can reduce the number of threads to save resources.
  5. Thread pool type: Different types of thread pools have different limits on the number of threads. For example, the number of threads in the FixedThreadPool fixed thread pool is fixed, and the number of threads in the CachedThreadPool cacheable thread pool is dynamically adjusted.

There are many factors to consider in this question, the easiest way is to go to测试

Divide the threads into different numbers, then observe the performance of the system and the execution of tasks, and gradually adjust the number of threads as needed to find the optimal configuration.

insert image description here

Thank you for watching! I hope this article can help you!
Column: "Java Learning Journey from Scratch" is constantly being updated, welcome to subscribe!
"Wish to encourage you and work together!"
insert image description here

Guess you like

Origin blog.csdn.net/m0_63463510/article/details/131409336