java multithreaded programming -- thread pool

Keywords: Java Back-end Multithreading

reference resources: https://blog.csdn.net/qq_27581243/article/details/86650682
https://www.cnblogs.com/zincredible/p/10984459.html

Thread is a heavyweight resource. The creation, startup and destruction of threads consume system resources. At the same time, it is limited by system resources. The relationship between the number of threads and system performance is a parabola. Therefore, thread management is a very good programming habit. Since JDK1.5, ExecutorService has been provided in utils package[ ɪɡˈ z ɛ kj ə t ɚ] Implementation of thread pool. Popular will: in order to avoid repeated creation of threads, the emergence of thread pool can allow threads to be reused. When work comes, a thread will be taken from the thread pool. When the work is completed, the thread will not be closed directly, but returned to the thread pool for other tasks.
A thread pool consists of the following four basic components:

1. Thread pool manager: used to create and manage thread pools, including creating thread pools, destroying thread pools, and adding new tasks;
2. PoolWorker: the thread in the thread pool is in a waiting state when there is no task, and can execute tasks circularly;
3. Task interface (task): the interface that must be implemented by each task for the work thread to schedule the execution of the task. It mainly specifies the entry of the task, the ending work after the task is executed, the execution status of the task, etc;
4. Task queue: used to store unprocessed tasks. It provides a buffer mechanism.

Role of thread pool

The function of thread pool is to limit the number of execution threads in the system.
According to the environment of the system, the number of threads can be set automatically or manually to achieve the best effect of operation. Less system resources are wasted, resulting in system congestion and low efficiency. The thread pool is used to control the number of threads, and other threads wait in line. After a task is executed, take the first task from the queue to start execution. If there is no waiting process in the queue, the thread pool is used This resource of the process pool is waiting. When a new task needs to run, if there are waiting worker threads in the thread pool, it can start running; otherwise, it enters the waiting queue.

The number of threads created and destroyed is reduced. Each worker thread can be reused and can perform multiple tasks.
The number of work line threads in the thread pool can be adjusted according to the bearing capacity of the system to prevent memory consumption due to too many threads and waste of system resources due to too few threads.

Creation of thread pool

The top-level interface of thread pool in Java is Executor, but strictly speaking, Executor is not a thread pool, but a tool for executing threads. The real thread pool interface is ExecutorService. It is complex to configure a thread pool, especially when the principle of thread pool is not very clear, it is likely that the configured thread pool is not better, Therefore, some static factories are provided in the Executors class to generate some common thread pools.

newSingleThreadExecutor
Note: initialize the thread pool with only one thread, and internally use LinkedBlockingQueue as the blocking queue.
Features: it is equivalent to a single thread serially executing all tasks. If the thread ends abnormally, a new thread will be created to continue to execute the tasks. The only thread can ensure the sequential execution of the submitted tasks
newFixedThreadPool
Description: initialize a thread pool with a specified number of threads, where corePoolSize == maxiPoolSize, and use linkedblockingqueue as the blocking queue
Features: each time a task is submitted, a thread will be created until the thread reaches the maximum size of the thread pool. Once the maximum size of the thread pool is reached, it will remain unchanged. Even when there are no executable tasks in the thread pool, the thread will not be released. If a thread ends due to execution exception, a new thread will be added to the thread pool.
newCachedThreadPool
Note: initialize a thread pool that can cache threads. This thread pool does not limit the size of the thread pool. The size of the thread pool completely depends on the maximum thread size that the operating system (or JVM) can create. The number of threads in the thread pool can reach Integer.MAX_VALUE, i.e. 2147483647. SynchronousQueue is used internally as the blocking queue;
Features: when there is no task execution, when the idle time of the thread exceeds keepAliveTime, the default is 60s, the thread resources will be automatically released; when submitting a new task, if there is no idle thread, a new thread will be created to execute the task, which will lead to certain system overhead;
Therefore, the number of concurrent tasks should be controlled to prevent performance degradation due to the creation of a large number of threads.
newScheduledThreadPool
Specific: the initialized thread pool can periodically execute the submitted tasks within the specified time. In the actual business scenario, the thread pool can be used to synchronize data regularly.
Summary: except for the special internal implementation of newScheduledThreadPool, the internal implementation of other thread pools is based on the ThreadPoolExecutor class (subclass of Executor).

Code demonstration:

1,newSingleThreadExecutor

package com.example.dtest.threadpool;

public class MyThread extends Thread{

    private int i;
    public MyThread(int in){
        this.i =in;
    }

    @Override
    public void run() {

        try {
            this.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(currentThread().getName()+"Execution:"+i);

    }
}
package com.example.dtest.threadpool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class NewSingleThreadExecutorTest {

    public static void main(String[] args) {

        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for(int i=0; i<10; i++){
            executorService.execute(new MyThread(i));
        }
        executorService.shutdown();
    }

}

2,newFixedThreadPool

package com.example.dtest.threadpool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class NewFixedThreadPoolTest {

    public static void main(String[] args) {

        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for(int i=0; i< 10; i++){
            executorService.execute(new MyThread(i));
        }
        executorService.shutdown();

    }

}

3,newCachedThreadPool

package com.example.dtest.threadpool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class NewCachedThreadPoolTest {

    public static void main(String[] args) {

        ExecutorService executorService = Executors.newCachedThreadPool();
        for(int i = 0; i < 10; i++){
            executorService.execute(new MyThread(i));
        }
        executorService.shutdown();
    }

}

4,newScheduledThreadPool

package com.example.dtest.threadpool.newScheduledThreadPool;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolTest02 {

    public static void main(String[] args) {
//        ScheduledThreadPoolExecutor atpe = new ScheduledThreadPoolExecutor(1); / / set the number of threads
//        for(int i = 0; i < 5; i++){
//            //Parameter 1: initialDelay indicates the delay time of the first task execution,
//            //Parameter 2: period indicates the interval between each task execution,
//            //Parameter 3: time interval value unit of TimeUnit.MILLISECONDS execution
//            atpe.scheduleAtFixedRate(new ScheduledThread(i),5,6, TimeUnit.SECONDS); / / execute the thread repeatedly at a fixed frequency
//        }

        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        Runnable r1 = () -> System.out.println("Thread Name:" + Thread.currentThread().getName() + ",implement:3 Execute in seconds");
        scheduledThreadPool.schedule(r1, 3, TimeUnit.SECONDS);
        Runnable r2 = () -> System.out.println("Thread Name:" + Thread.currentThread().getName() + ",implement:Every 3 seconds after a delay of 2 seconds");
        scheduledThreadPool.scheduleAtFixedRate(r2, 2, 3, TimeUnit.SECONDS);
        Runnable r3 = () -> System.out.println("Thread Name:" + Thread.currentThread().getName() + ",implement:General tasks");
        for (int i = 0; i < 5; i++) {
            scheduledThreadPool.execute(r3);
        }

    }

}

Posted by yumico23 on Mon, 29 Nov 2021 17:18:16 -0800