判断线程池任务执行完成 淡淡的烟草味﹌ 2022-05-11 10:54 259阅读 0赞 ## 前言 ## 线程池执行任务,有时候,我们需要知道它是什么时候完成的。 ## 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(); } } ![ContactAuthor][] [ContactAuthor]: /images/20220505/ff0d620e752d4da3bd3f562278c34f3d.png
还没有评论,来说两句吧...