多任务并发时,该怎样判断线程池中的任务都已经执行完毕?
2023-09-11 14:21:18 时间
开发中常常遇到需要用线程池来解决多任务并发的问题,在使用JUC下的线程池执行并发任务之后,往往很难判断任务是不是都执行完成,但是这种判断又是非常必要的。下面就介绍三种常用的判断所有任务是否执行完毕的方法。
1,利用线程池自身的 isTerminated()方法。
boolean isTerminated()
如果关闭后所有任务都已完成,则返回 true。注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。
public class EsPoolShutDownDemo {
public static void main(String[] args){
//开启线程池,corePoolSize为10 。
ExecutorService esPool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10000000; i++) {
final int num = i;
Runnable task = new Runnable() {
public void run() {
try {
//线程执行任务
System.out.println(num);
} catch (Exception e) {
e.printStackTrace();
}
}
};
esPool.submit(task);
}
//停止线程池
esPool.shutdown();
while(true) {
//只有当线程池中所有线程完成任务时才会返回true,并且需要先调用线程池的shutdown方法或者shutdownNow方法。
if(esPool.isTerminated()) {
System.out.println("All finished");
}
}
}
}
2,使用CountDownLatch
CountDownLatch能够使一个或多个线程等待其他线程完成各自的工作后再执行;
public class CountDownLatchDemo {
public static void main(String[] args) {
//定义总共需要执行的任务数
final int nThreads = 10;
final CountDownLatch endGate = new CountDownLatch(nThreads);
ExecutorService exec = Executors.newCachedThreadPool();
for (int i = 0; i < nThreads; i++) {
final int num = i;
Runnable task = new Runnable() {
public void run() {
try {
//执行任务
System.out.println(num);
} catch (Exception e) {
e.printStackTrace();
} finally {
//计数器减少数量
endGate.countDown();
}
}
};
exec.submit(task);
}
try {
//等待计数器数字减到0,即等待到所有任务完成。当减到0之后才会继续执行后面的代码
endGate.await();
System.out.println("All finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3,使用Semaphore
Semaphore类是一个计数信号量,必须由获取它的线程释放, 通常用于限制可以访问某些资源(物理或逻辑的)线程数目。
public class SemaphoreDemo {
public static void main(String[] args){
final Semaphore semaphore = new Semaphore(10);
//开启线程池,corePoolSize为10 。
ExecutorService exec = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10000000; i++) {
final int num = i;
Runnable task = new Runnable() {
public void run() {
try {
//获取锁
semaphore.acquire();
//线程执行任务
System.out.println(num);
//释放锁
semaphore.release();
} catch (Exception e) {
e.printStackTrace();
}
}
};
exec.submit(task);
}
//停止线程池
exec.shutdown();
try {
//当线程池中线程执行完任务之前一直阻塞
//或者任务没执行完,但是到了1小时的过期时间之后,也会解除阻塞
exec.awaitTermination(1, TimeUnit.HOURS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
上面3个方法中,第一个最普遍,后两个使用少一些。性能方面,第一种和第三种较好,推荐使用。
码字不易,如果觉得有帮助,一定要给我点赞哟~~
不然信不信我砸了你家灯,半夜偷亲你 ( ̄ε  ̄) !!!
相关文章
- Oracle官方并发教程之线程池
- 并发编程4-容器
- Redis自旋锁解决分布高并发问题:使线程异步变为同步执行
- 8-4python语法基础-并发编程-进程线程协程,实战练习
- 说说Android的广播(2) - 并发队列和串行队列
- [Design] 后端程序的高并发与异步
- Atitit.软件与编程语言中的锁机制原理attilax总结 1. 用途 (Db,业务数据加锁,并发操作加锁。2 2. 锁得类型3 2.1. 排它锁 “互斥锁 共享锁 乐观锁与悲观锁 乐观锁:
- 【项目实战】并发编程之线程池(ExecutorService接口与Executors)入门介绍
- QT-线程并发、QTcpServer并发、QThreadPool线程池
- 带你熟悉3种AQS的线程并发工具的用法
- 【华为云技术分享】解密TaurusDB存储端高并发之线程池
- QT-线程并发、QTcpServer并发、QThreadPool线程池
- Java并发编程:进程和线程之由来
- 使用multi curl进行http并发访问
- 【高并发】高并发场景下如何优化加锁方式?看完这篇我确实明白了!!
- 高并发之——线程与多线程
- 漫谈并发编程(二):java线程的创建与基本控制
- c# 并发与异步 一、线程创建 汇合 休眠 阻塞
- c# 并发与异步 二、变量 锁 前后台线程 优先级 信号