判断线程池任务执行完成
前言
线程池执行任务,有时候,我们需要知道它是什么时候完成的。
1、.shutdown()、.isTerminated()进行判断
下面方法的解释:
当调用ExecutorService.shutdown方法的时候,线程池不再接收任何新任务,但此时线程池并不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。解释退出了,如果在给新任务就会报错,一般不使用这种方法,建议使用第二种,这样线程池还可以用。
for(Long key:map.keySet()){
final List<Long> idsThread = ids ;
threadPoolUtils.execute(()->{
List<Long> idParams = idsThread.subList(key.intValue()-1, map.get(key).intValue());
final List<CouponItemGood> couponItemGoodFinal = couponItemGoodMapper.dataCpuponItemGoodfindByParamsIds(idParams);
if (listKeyMonitor(couponItemGoodFinal, true,couponCheckVailds,mode)){
return;
}
});
}
threadPoolUtils.getThreadPoolExecutor().shutdown();
while(true){
if(threadPoolUtils.getThreadPoolExecutor().isTerminated()){
System.out.println("所有的子线程都结束了!");
break;
}
Thread.sleep(10000); //防止while判断过快,浪费资源,这里我设置为10秒大家看情况设置
}
1.2、shutdown()、shutdownNow()、awaitTerminate(long timeout,TimeUnit unit)区别
1、shutdown()
问:shutdown()有什么功能?
答:阻止新来的任务提交,对已经提交了的任务不会产生任何影响。当已经提交的任务执行完后,它会将那些闲置的线程(idleWorks)进行中断,这个过程是异步的。
问:如何阻止新来的任务提交?
答:通过将线程池的状态改成SHUTDOWN,当再将执行execute提交任务时,如果测试到状态不为RUNNING,则抛出rejectedExecution,从而达到阻止新任务提交的目的。
问:为何对提交的任务不产生任何影响?
答:在调用中断任务的方法时,它会检测workers中的任务,如果worker对应的任务没有中断,并且是空闲线程,它才会去中断。 另外的话,workQueue中的值,还是按照一定的逻辑顺序不断的往works中进行输送的,这样一来,就可以保证提交的任务按照线程本身的逻辑执行,不受到影响。
2、shutdownNow()
问:shutdownNow()有什么功能?
答:阻止新来的任务提交,同时会中断当前正在运行的线程,即workers中的线程。 另外它还将workQueue中的任务给移除,并将这些任务添加到列表中进行返回。
问:如何阻止新来的任务提交?
答:通过将线程池的状态改成STOP,当再将执行execute提交任务时,如果测试到状态不为RUNNING,则抛出rejectedExecution,从而达到阻止新任务提交的目的.
问:如果我提交的任务代码块中,正在等待某个资源,而这个资源没到,但此时执行shutdownNow(),会出现什么情况?
答:当执行shutdownNow()方法时,如遇已经激活的任务,并且处于阻塞状态时,shutdownNow()会执行1次中断阻塞的操作,此时对应的线程报InterruptedException,如果后续还要等待某个资源,则按正常逻辑等待某个资源的到达。例如,一个线程正在sleep状态中,此时执行shutdownNow(),它向该线程发起interrupt()请求,而sleep()方法遇到有interrupt()请求时,会抛出InterruptedException(),并继续往下执行。在这里要提醒注意的是,在激活的任务中,如果有多个sleep(),该方法只会中断第一个sleep(),而后面的仍然按照正常的执行逻辑进行。
3、awaitTermination(long timeout,TimeUnit unit)
简单来说,awaitTermination会一直等待,直到线程池状态为TERMINATED或者,等待的时间到达了指定的时间。
exec.shutdown();
exec.awaitTermination(1, TimeUnit.HOURS);
2、使用执行任务数量进行判断
for(Long key:map.keySet()){
final List<Long> idsThread = ids ;
threadPoolUtils.execute(()->{
List<Long> idParams = idsThread.subList(key.intValue()-1, map.get(key).intValue());
final List<CouponItemGood> couponItemGoodFinal = couponItemGoodMapper.dataCpuponItemGoodfindByParamsIds(idParams);
if (listKeyMonitor(couponItemGoodFinal, true,couponCheckVailds,mode)){
return;
}
});
}
//当线程池完成的线程数等于线程池中的总线程数
boolean allThreadsIsDone = threadPoolUtils.getThreadPoolExecutor().getTaskCount() == threadPoolUtils.getThreadPoolExecutor().getCompletedTaskCount();
log.info("\n"+allThreadsIsDone+"当前线程池完成状态:线程池工作任务数量"+threadPoolUtils.getThreadPoolExecutor().getTaskCount()+"线程池完成工作数量"+threadPoolUtils.getThreadPoolExecutor().getCompletedTaskCount());
while (!allThreadsIsDone) {
allThreadsIsDone = threadPoolUtils.getThreadPoolExecutor().getTaskCount() == threadPoolUtils.getThreadPoolExecutor().getCompletedTaskCount();
if (allThreadsIsDone) {
break;
}
try {
log.info("\n"+allThreadsIsDone+"当前线程池完成状态:线程池工作任务数量"+threadPoolUtils.getThreadPoolExecutor().getTaskCount()+"线程池完成工作数量"+threadPoolUtils.getThreadPoolExecutor().getCompletedTaskCount());
Thread.sleep(10000); //睡上10秒钟吧
} catch (InterruptedException e) {
e.printStackTrace();
}
}
感兴趣的,欢迎添加博主微信,
哈,博主很乐意和各路好友交流,如果满意,请打赏博主任意金额,感兴趣的在微信转账的时候,备注您的微信或者其他联系方式。添加博主微信哦。
请下方留言吧。可与博主自由讨论哦
支付包 | 微信 | 微信公众号 |
---|---|---|
![]() |
![]() |
![]() |