当前位置:网站首页>How to judge that the thread pool has completed all tasks?
How to judge that the thread pool has completed all tasks?
2022-07-05 10:11:00 【A bird carved in the desert】
A lot of scenarios , We need to wait for all tasks of the thread pool to be executed , Then proceed to the next step . For threads Thread Come on , Well done , Add one more join The solution is solved , However, the judgment of thread pool is more troublesome .
We provide 4 A method to judge whether thread pool tasks have been executed :
- Use isTerminated Methods to judge .
- Use getCompletedTaskCount Methods to judge .
- Use CountDownLatch Judge .
- Use CyclicBarrier Judge .
Let's take a look at one by one .
The problem of not judging
If you don't judge whether the thread pool has been executed , The following problems will occur , As shown in the following code :
import java.util.Random;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolCompleted {
public static void main(String[] args) {
// Creating a thread pool
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 20,
0, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1024));
// Add tasks
addTask(threadPool);
// Print the results
System.out.println(" Thread pool task execution completed !");
}
/**
* Add tasks to the thread pool
*/
private static void addTask(ThreadPoolExecutor threadPool) {
// Total tasks
final int taskCount = 5;
// Add tasks
for (int i = 0; i < taskCount; i++) {
final int finalI = i;
threadPool.submit(new Runnable() {
@Override
public void run() {
try {
// Random sleep 0-4s
int sleepTime = new Random().nextInt(5);
TimeUnit.SECONDS.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(String.format(" Mission %d Execution completed ", finalI));
}
});
}
}
}
The results of the above procedures are as follows :
As can be seen from the above execution results , The program prints first “ Thread pool task execution completed !”, Then it is still executing the task of thread pool in succession , The result of this chaotic execution sequence , Not what we expected . The result we want is when all the tasks are completed , Re print “ Thread pool task execution completed !” Information about .
The reason for the above problem is that the main thread main, And thread pool are executed concurrently , So when the thread pool is not finished ,main The print result code of the thread has been executed . I want to solve this problem , You need to print the results before , First, judge whether the tasks of the thread pool have been fully executed , If not, wait for the task to be executed before printing the results .
Method 1:isTerminated
We can take advantage of the termination state of the thread pool (TERMINATED) To determine whether all the tasks of the thread pool have been executed , But I want the state of the thread pool to change , We need to call the thread pool shutdown Method , Otherwise, the thread pool will always be in RUNNING Running state , Then there is no way to use the termination status to judge whether the task has been completely executed , Its implementation code is as follows :
import java.util.Random;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Thread pool task execution completion judgment
*/
public class ThreadPoolCompleted {
public static void main(String[] args) {
// 1. Creating a thread pool
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 20,
0, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1024));
// 2. Add tasks
addTask(threadPool);
// 3. Judge whether the thread pool has been executed
isCompleted(threadPool); // 【 Core call method 】
// 4. Thread pool finished executing
System.out.println();
System.out.println(" Thread pool task execution completed !");
}
/**
* Method 1:isTerminated Realization way
* Judge whether all tasks of the thread pool have been executed
*/
private static void isCompleted(ThreadPoolExecutor threadPool) {
threadPool.shutdown();
while (!threadPool.isTerminated()) { // If it is not finished, it will continue to loop
}
}
/**
* Add tasks to the thread pool
*/
private static void addTask(ThreadPoolExecutor threadPool) {
// Total tasks
final int taskCount = 5;
// Add tasks
for (int i = 0; i < taskCount; i++) {
final int finalI = i;
threadPool.submit(new Runnable() {
@Override
public void run() {
try {
// Random sleep 0-4s
int sleepTime = new Random().nextInt(5);
TimeUnit.SECONDS.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(String.format(" Mission %d Execution completed ", finalI));
}
});
}
}
}
Method statement :shutdown The method is to start the orderly shutdown of the thread pool , It will complete all the submitted tasks before it is completely closed , And will not accept any new tasks . When all the tasks in the thread pool have been executed , The thread pool enters the termination state , call isTerminated Method returns the result that true 了 .
The results of the above procedures are as follows :
Defect analysis :
Need to close thread pool .
Expand : All States of the thread pool
The thread pool contains the following 5 States :
RUNNING: Running state .
SHUTDOWN: The closed position .
STOP: Blocking state .
TIDYING: Sorting status .
TERMINATED: Termination status .
If you don't call the thread pool shutdown method , Then the thread pool will always be in RUNNING Running state .
Method 2:getCompletedTaskCount
We can judge the number of planned tasks and completed tasks in the thread pool , To determine whether the thread pool has been fully executed , If the number of tasks planned to be executed = Number of tasks completed , Then all the tasks of the thread pool will be executed , Otherwise, it will not be completed , The specific implementation code is as follows :
/**
* Method 2:getCompletedTaskCount Realization way
* Judge whether all tasks of the thread pool have been executed
*/
private static void isCompletedByTaskCount(ThreadPoolExecutor threadPool) {
while (threadPool.getTaskCount() != threadPool.getCompletedTaskCount()) {
}
}
The results of the above procedures are as follows :
Method statement
getTaskCount(): Returns the total number of scheduled tasks . Because the state of tasks and threads may change dynamically during the calculation process , So the value returned is just an approximation .
getCompletedTaskCount(): Returns the total number of tasks completed . Because the state of tasks and threads may change dynamically during calculation , So the returned value is only an approximation , But it doesn't decrease in successive calls .
Analysis of advantages and disadvantages
The advantage of this implementation is that there is no need to close the thread pool . Its disadvantages are getTaskCount() and getCompletedTaskCount() What is returned is an approximate value , Because the tasks in the thread pool and the state of threads may change dynamically during the calculation process , So both of them return an approximate value .
Method 3:CountDownLatch
CountDownLatch It can be understood as a counter , We created an include N Counters for tasks , Counter after each task is executed -1, Until the counter goes down to 0 when , It means that all tasks have been performed , Then you can execute the code of the next business , Its implementation process and specific implementation code are as follows :
public static void main(String[] args) throws InterruptedException {
// Creating a thread pool
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 20,
0, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1024));
final int taskCount = 5; // Total tasks
// Single counter
CountDownLatch countDownLatch = new CountDownLatch(taskCount); // ①
// Add tasks
for (int i = 0; i < taskCount; i++) {
final int finalI = i;
threadPool.submit(new Runnable() {
@Override
public void run() {
try {
// Random sleep 0-4s
int sleepTime = new Random().nextInt(5);
TimeUnit.SECONDS.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(String.format(" Mission %d Execution completed ", finalI));
// The thread is finished , Counter -1
countDownLatch.countDown(); // ②
}
});
}
// Blocking waits for the thread pool task to finish executing
countDownLatch.await(); // ③
// Thread pool finished executing
System.out.println();
System.out.println(" Thread pool task execution completed !");
}
Code instructions : The above code is marked as ①、②、③ The line of code is the core implementation code , among : ① Is a declaration that contains 5 Counters for tasks ; ② Is the counter after each task is executed -1; ③ Is the blocking wait counter CountDownLatch Reduced to 0, Indicates that the tasks have been completed , It can be executed await The business code behind the method .
The results of the above procedures are as follows :
Analysis of advantages and disadvantages
CountDownLatch The writing is elegant , And there is no need to close the thread pool , But its disadvantage is that it can only be used once ,CountDownLatch Cannot be reused after being created , in other words CountDownLatch It can be understood as a counter that can only be used once .
Method 4:CyclicBarrier
CyclicBarrier and CountDownLatch similar , It can be understood as a reusable loop counter ,CyclicBarrier You can call reset Method resets itself to the initial state ,CyclicBarrier The specific implementation code is as follows :
public static void main(String[] args) throws InterruptedException {
// Creating a thread pool
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 20,
0, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1024));
final int taskCount = 5; // Total tasks
// Cycle counter ①
CyclicBarrier cyclicBarrier = new CyclicBarrier(taskCount, new Runnable() {
@Override
public void run() {
// Thread pool finished executing
System.out.println();
System.out.println(" All tasks of thread pool have been executed !");
}
});
// Add tasks
for (int i = 0; i < taskCount; i++) {
final int finalI = i;
threadPool.submit(new Runnable() {
@Override
public void run() {
try {
// Random sleep 0-4s
int sleepTime = new Random().nextInt(5);
TimeUnit.SECONDS.sleep(sleepTime);
System.out.println(String.format(" Mission %d Execution completed ", finalI));
// The thread is finished
cyclicBarrier.await(); // ②
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
});
}
}
The results of the above procedures are as follows :
Method statement
CyclicBarrier Yes 3 An important way :
Construction method : The constructor can pass two parameters , Parameters 1 Is the number of counters parties, Parameters 2 Yes, the counter is 0 when , That is, the event that can be executed after all tasks are executed ( Method ).
await Method : stay CyclicBarrier Blocking and waiting on , When this method is called CyclicBarrier Your internal counter will -1, Until one of the following happens :
stay CyclicBarrier The number of threads waiting on the parties, That is, the declared number of counters , All threads are released , Carry on .
The current thread is interrupted , Throw out InterruptedException abnormal , And stop waiting , Carry on .
Other waiting threads are interrupted , The current thread throws BrokenBarrierException abnormal , And stop waiting , Carry on .
Other waiting threads time out , The current thread throws BrokenBarrierException abnormal , And stop waiting , Carry on .
Other thread calls CyclicBarrier.reset() Method , The current thread throws BrokenBarrierException abnormal , And stop waiting , Carry on .
reset Method : bring CyclicBarrier Return to the initial state , Intuitively, it does two things :
If there are waiting threads , It will be thrown out. BrokenBarrierException abnormal , And these threads stop waiting , Carry on .
Will the mark be damaged or not broken Set as false.
Analysis of advantages and disadvantages
CyclicBarrier The complexity from design to use is higher than CountDownLatch, Compared with CountDownLatch Its advantage is that it can be reused ( Just call reset You can return to your original state ), The disadvantage is that it is difficult to use .
summary
We provide 4 A method to judge whether thread pool tasks have been executed :
1、 Use isTerminated Methods to judge : By judging the completion status of the thread pool , Need to close thread pool , Generally not recommended .
2、 Use getCompletedTaskCount Methods to judge : The total number of tasks executed and completed through the plan , To determine whether the tasks of the thread pool have been fully executed , If they are equal, it is determined that all execution is completed . But because thread individuals and states change , So what you get is a rough value , May not be accurate .
3、 Use CountDownLatch Judge : Equivalent to a thread safe single counter , It's easy to use , And there is no need to close the thread pool , It is a common judgment method .
4、 Use CyclicBarrier Judge : Equivalent to a thread safe repeat counter , But the use is more complex , Therefore, it is less used in daily projects .
边栏推荐
- 如何獲取GC(垃圾回收器)的STW(暫停)時間?
- Glide advanced level
- How to use sqlcipher tool to decrypt encrypted database under Windows system
- Uni app running to wechat development tool cannot Preview
- Wechat applet - simple diet recommendation (3)
- MySQL digital type learning notes
- Cerebral Cortex:有向脑连接识别帕金森病中广泛存在的功能网络异常
- Mysql80 service does not start
- leetcode:1200. 最小绝对差
- How to get the STW (pause) time of GC (garbage collector)?
猜你喜欢
最全是一次I2C总结
Getting started with Apache dolphin scheduler (one article is enough)
自动化规范检查软件如何发展而来?
Evolution of Baidu intelligent applet patrol scheduling scheme
盗版DALL·E成梗图之王?日产5万张图像,挤爆抱抱脸服务器,OpenAI勒令改名
uniapp + uniCloud+unipay 实现微信小程序支付功能
学习笔记5--高精地图解决方案
程序员搞开源,读什么书最合适?
QT realizes signal transmission and reception between two windows
Cut off 20% of Imagenet data volume, and the performance of the model will not decline! Meta Stanford et al. Proposed a new method, using knowledge distillation to slim down the data set
随机推荐
Cent7 Oracle database installation error
【小技巧】獲取matlab中cdfplot函數的x軸,y軸的數值
StaticLayout的使用详解
橫向滾動的RecycleView一屏顯示五個半,低於五個平均分布
Meitu lost 300 million yuan in currency speculation for half a year. Huawei was exposed to expand its enrollment in Russia. Alphago's peers have made another breakthrough in chess. Today, more big new
MySQL digital type learning notes
ConstraintLayout的流式布局Flow
Apache dolphin scheduler system architecture design
美图炒币半年亏了3个亿,华为被曝在俄罗斯扩招,AlphaGo的同类又刷爆一种棋,今日更多大新闻在此...
高级 OpenCV:BGR 像素强度图
Tianlong Babu TLBB series - single skill group injury
La vue latérale du cycle affiche cinq demi - écrans en dessous de cinq distributions moyennes
天龙八部TLBB系列 - 关于技能冷却和攻击范围数量的问题
Dedecms website building tutorial
基于单片机步进电机控制器设计(正转反转指示灯挡位)
把欧拉的创新带向世界 SUSE 要做那个引路人
程序员如何活成自己喜欢的模样?
TDengine × Intel edge insight software package accelerates the digital transformation of traditional industries
如何获取GC(垃圾回收器)的STW(暂停)时间?
苹果 5G 芯片研发失败?想要摆脱高通为时过早