The thread pool
1. Introduction
The idea of pools, you have connection pools in databases, constant pools in strings, and so on.
In order to “prevent the time loss of connection creation and destruction during use”, we choose to create a part of connections when the service is started for subsequent use, and put them into the pool after use, forming the concept of reuse and the emergence of the pool.
The same is true for thread pools, where a pool is initialized at service startup via Spring or static methods, etc. All subsequent requests are added directly to the pool, and threads in the pool directly execute the tasks added to the pool.
The thread pool has a core thread count, which is the number of threads that a thread has at its inception, and when the core thread count is insufficient to process an incoming task, that task is added to the blocking queue.
When the blocking queue is saturated, the thread pool creates threads again until the maximum number of threads is reached.
If the maximum number of threads has been reached and the task cannot be processed, the task is rejected according to the specified rejection policy.
When the number of tasks is small, the thread is idle, and when the idle time exceeds the maximum we specify, the thread pool will destroy it.
2. Basic parameters of the thread pool
From the above, it is easy to know what parameters a thread pool needs.
First, an initialization thread number, coreSize
- A blocking queue,
BlockingQueue
- A maximum number of threads,
maxSize
- A rejection strategy,
RejectedExecutionHandler
- A maximum idle time and unit of time,
keepAliveTime
andtimeUnit
- There’s also a thread project that helps us create a thread
threadFactory
These are the seven parameters of a thread pool, from which we build a thread pool
3. Customize the thread pool
“This thread pool only simulates the use of four parameters: core thread, maximum thread, and maximum queue length“
“The task class“
public class MyTask implements Runnable{
int id ;
public MyTask(int id) {
this.id = id; } @Override public void run(a) { String name = Thread.currentThread().getName(); System.out.println(name+"\ T about to embark on a mission"+id); try {Thread.sleep(200); }catch(InterruptedException e) {e.printStackTrace(); } System.out.println(name+"\ T has fulfilled its mission"); } @Override public String toString(a) { return "MyTask{" + "id=" + id + '} '; } } Copy the code
“Thread class“
/ * ** A custom thread* /
public class MyThread extends Thread{
private String name ;
private List<Runnable> tasks ; public MyThread(String name, List<Runnable> tasks) { this.name = name; this.tasks = tasks; } @Override public void run(a) { while(tasks.size()>0) { Runnable remove = tasks.remove(0); remove.run(); } } } Copy the code
“The thread pool class“
/ * ** Custom thread pools* /
public class MyPool {
private int currentPoolSize ; private int corePoolSize ; private int maxPoolSize ; private int workSize ; private List<Runnable> tasks = new CopyOnWriteArrayList<>(); public MyPool(int corePoolSize, int maxPoolSize, int workSize) { this.corePoolSize = corePoolSize; this.maxPoolSize = maxPoolSize; this.workSize = workSize; } public void sumbit(Runnable runnable){ // If the number of current threads is smaller than the number of core threads if(tasks.size()>=workSize){ System.out.println("Task dropped"); }else{ tasks.add(runnable); this.execTask(runnable); } } public void execTask(Runnable runnable){ if(currentPoolSize <= corePoolSize){ new MyThread("Thread"+currentPoolSize,tasks).start(); currentPoolSize++; }else if(currentPoolSize < maxPoolSize){ new MyThread("Non-core thread"+currentPoolSize,tasks).start(); currentPoolSize++; }else{ System.out.println(runnable+"Task cached"); } } } Copy the code
“actuator“
public class MyThreadPollTest {
public static void main(String[] args) {
MyPool myPool = new MyPool(2.4.20);
for (int i = 0; i < 30; i++) {
MyTask myTask = new MyTask(i);
myPool.sumbit(myTask); } } } Copy the code
“follower“
yTask{id=4} Tasks are cachedMyTask{id=5} Tasks are cachedMyTask{id=6} Tasks are cachedMyTask{id=7} Tasks are cachedMyTask{id=8} Tasks are cachedMyTask{id=9} Tasks are cachedMyTask{id=10} Tasks are cachedMyTask{id=11} Tasks are cachedMyTask{id=12} Tasks are cachedMyTask{id=13} Tasks are cachedMyTask{id=14} Tasks are cachedMyTask{id=15} Tasks are cachedMyTask{id=16} Tasks are cachedMyTask{id=17} Tasks are cachedMyTask{id=18} Tasks are cachedMyTask{id=19} Tasks are cachedThread-3Upcoming mission2 Thread-2Upcoming mission1 Thread-1Upcoming mission0 MyTask{id=20} Tasks are cachedMyTask{id=21} Tasks are cachedMyTask{id=22} Tasks are cachedThread-0Upcoming mission3 MyTask{id=23} Tasks are cachedTask discardedTask discardedTask discardedTask discardedTask discardedTask discardedThread-3Finished the jobThread-3Upcoming mission4 Thread-2Finished the jobThread-2Upcoming mission5 Thread-1Finished the jobThread-1Upcoming mission6 Thread-0Finished the jobThread-0Upcoming mission7 Thread-1Finished the jobThread-3Finished the jobThread-1Upcoming mission8 Thread-3Upcoming mission9 Thread-0Finished the jobThread-2Finished the jobThread-2Upcoming mission10 Thread-0Upcoming mission11 Thread-3Finished the jobThread-1Finished the jobThread-1Upcoming mission12 Thread-3Upcoming mission13 Thread-0Finished the jobThread-0Upcoming mission14 Thread-2Finished the jobThread-2Upcoming mission15 Thread-1Finished the jobThread-1Upcoming mission16 Thread-3Finished the jobThread-3Upcoming mission17 Thread-2Finished the jobThread-0Finished the jobThread-0Upcoming mission19 Thread-2Upcoming mission18 Thread-3Finished the jobThread-1Finished the jobThread-1Upcoming mission21 Thread-3Upcoming mission20 Thread-0Finished the jobThread-0Upcoming mission22 Thread-2Finished the jobThread-2Upcoming mission23 Thread-1Finished the jobThread-3Finished the jobThread-0Finished the jobThread-2Finished the jobCopy the code
4. Java thread pools
“Thread architecture diagram“
Java provides a Executors class to get some specific threads
4.1 Thread pool without core threads
public static ExecutorService newCachedThreadPool(a) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); } Copy the code
4.2 Singleton thread pool
This thread pool creates only one core thread
public static ExecutorService newSingleThreadExecutor(a) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1.1. 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
} public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1.1. 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory)); } Copy the code
4.3 Timing thread Pool
A thread pool that can execute scheduled tasks
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public static ScheduledExecutorService newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory) { return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); } Copy the code
scheduleAtFixedRate
The interval includes the time to perform the taskscheduleWithFixedDelay
The interval does not include the time to execute the task
4.4 ThreadPoolExecutor
This is a thread pool provided by Java, and we often use this custom thread pool directly in development
“Construction method:“
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) Copy the code
Let’s focus on blocking queues and rejection policies.
4.4.1 Blocking queues
BlockingQueue is an interface. Take a look at its inheritance diagram
ArrayBlockingQueue
A bounded blocking queue consisting of arraysLinkedBlockingQueue
A bounded blocking queue consisting of linked listsSynchronousQueue
Queues that do not store elements, but only one queueLinkedBlockingQueue
A double-ended bounded queue.PriorityBlockingQueue
A bounded queue that supports priority sortingDelayQueue
Delayed-unbounded queues implemented using priority queuesLinkedTransferQueue
An unbounded blocking queue consisting of a linked list structure
“Three ways of execution“
- Throw an exception.
The add () and remove ()
java.lang.IllegalStateException
Copy the code
- Returns Boolean or NULL.
offer
andpoll
Add backfalse; Remove returnnull
Copy the code
- The thread is blocked.
put
andtake
- Look at the elements that follow
element
andpeek
4.4.2 Rejection Policy
The default denial strategy for thread pools is to throw an exception directly
There are four rejection policies for thread pools
AbortPolicy
Throws an exception directly, rejecting the policy by defaultCallerRunsPolicy
Return the task to the caller for execution, that is, to the thread in the thread pool for executionDiscardPolicy
Direct refused toDiscardOldestPolicy
Try to dequeue the queue that has waited the longest and add the latest one to the queue
4.4.3 Setting Thread Pool Parameters
According to the 8020 principle, the system generates 100 tasks per second in 80% of the time, and the execution time of a task is 0.1 second. A maximum of 1000 tasks can be generated in a second
- Number of core threads.
100 * 0.1 = 10
- Task queue length.
100 * 2 = 200
- Maximum number of threads.
(Maximum number of tasks - Task queue length) x execution time of a single task (1000-200) x 0.1=800
5. ExecutorService
There is an ExecutorService in the thread pool inheritance architecture above. This is the thread pool interface built into Java
void shutdown(a)Initiates a sequential shutdown that executes previously submitted tasks but does not accept new tasks.List<Runnable> shutdownNow(a)Stop all tasks in progress, pause processing of waiting tasks, and return to the list of tasks waiting to be executed.<T> Future<T> submit(Callable<T> task)Performs a task with a return value that returns a Future object.Future<? >submit(Runnable task)Execute the Runnable task and return a Future representing the task.<T> Future<T> submit(Runnable task, T result)Execute the Runnable task and return a Future representing the task.Copy the code
Previous recommendations:
This article takes you through the architectural thinking of Spring MVC
Mybatis you only know CRUD
You know the IOC structure
This article is formatted using MDNICE