判断线程池任务执行完成

前言

线程池执行任务,有时候,我们需要知道它是什么时候完成的。

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();
    }
}






感兴趣的,欢迎添加博主微信,

哈,博主很乐意和各路好友交流,如果满意,请打赏博主任意金额,感兴趣的在微信转账的时候,备注您的微信或者其他联系方式。添加博主微信哦。


请下方留言吧。可与博主自由讨论哦

支付包 微信 微信公众号
支付宝 微信 微信公众号
posted @ 2018-10-19 15:09  HealerJean  阅读(602)  评论(0编辑  收藏  举报