时间:2021-05-20
使用ExecutorService来停止线程服务
之前的文章中我们提到了ExecutorService可以使用shutdown和shutdownNow来关闭。
这两种关闭的区别在于各自的安全性和响应性。shutdownNow强行关闭速度更快,但是风险也更大,因为任务可能正在执行的过程中被结束了。而shutdown正常关闭虽然速度比较慢,但是却更安全,因为它一直等到队列中的所有任务都执行完毕之后才关闭。
使用shutdown
我们先看一个使用shutdown的例子:
public void useShutdown() throws InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(10); Runnable runnableTask = () -> { try { TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } }; executor.submit(runnableTask); executor.shutdown(); executor.awaitTermination(800, TimeUnit.MILLISECONDS); }awaitTermination将会阻塞直到所有正在执行的任务完成,或者达到指定的timeout时间。
使用shutdownNow
当通过shutdownNow来强行关闭ExecutorService是, 它会尝试取消正在执行的任务,并返回所有已经提交但是还没有开始的任务。从而可以将这些任务保存起来,以便以后进行处理。
但是这样我们只知道了还没有开始执行的任务,对于那些已经开始执行但是没有执行完毕却被取消的任务我们无法获取。
我们看下如何获得开始执行但是还没有执行完毕的任务:
public class TrackingExecutor extends AbstractExecutorService { private final ExecutorService executorService; private final Set<Runnable> taskCancelledAtShutdown= Collections.synchronizedSet(new HashSet<Runnable>()); public TrackingExecutor(ExecutorService executorService){ this.executorService=executorService; } @Override public void shutdown() { executorService.shutdown(); } @Override public List<Runnable> shutdownNow() { return executorService.shutdownNow(); } @Override public boolean isShutdown() { return executorService.isShutdown(); } @Override public boolean isTerminated() { return executorService.isTerminated(); } @Override public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { return executorService.awaitTermination(timeout,unit); } @Override public void execute(Runnable command) { executorService.execute(() -> { try { command.run(); }finally { if(isShutdown() && Thread.currentThread().isInterrupted()){ taskCancelledAtShutdown.add(command); } } }); } public List<Runnable> getCancelledTask(){ if(! executorService.isTerminated()){ throw new IllegalStateException("executorService is not terminated"); } return new ArrayList<>(taskCancelledAtShutdown); }}上面的例子中我们构建了一个新的ExecutorService,他传入一个ExecutorService,并对其进行封装。
我们重写了execute方法,在执行完毕判断该任务是否被中断,如果被中断则将其添加到CancelledTask列表中。
并提供一个getCancelledTask方法来返回未执行完毕的任务。
我们看下怎么使用:
public void useShutdownNow() throws InterruptedException { TrackingExecutor trackingExecutor=new TrackingExecutor(Executors.newCachedThreadPool()); Runnable runnableTask = () -> { try { TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } }; trackingExecutor.submit(runnableTask); List<Runnable> notrunList=trackingExecutor.shutdownNow(); if(trackingExecutor.awaitTermination(800, TimeUnit.SECONDS)){ List<Runnable> runButCancelledList= trackingExecutor.getCancelledTask(); } }trackingExecutor.shutdownNow()返回的是未执行的任务。而trackingExecutor.getCancelledTask()返回的是被取消的任务。
上面的任务其实还有一个缺点,因为我们在存储被取消的任务列表的额时候taskCancelledAtShutdown.add(command),因为之前的判断不是原子操作,则可能会产生误报。
本文的例子请参考https://github.com/ddean2009/learn-java-concurrency/tree/master/ExecutorServiceShutdown
到此这篇关于Java使用ExecutorService来停止线程服务的文章就介绍到这了,更多相关Java ExecutorService停止线程内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
Java线程池ExecutorService1.线程池 1.1什么情况下使用线程池单个任务处理的时间比较短.将需处理的任务的数量大.1.2使用线程池的好处减少在
Java中停止线程的原则是什么?在Java中,最好的停止线程的方式是使用中断interrupt,但是这仅仅是会通知到被终止的线程"你该停止运行了",被终
这篇是Java多线程基本用法的一个总结。本篇文章会从一下几个方面来说明Java多线程的基本用法:如何使用多线程如何得到多线程的一些信息如何停止线程如何暂停线程线
本文实例讲述了Java通过在主循环中判断Boolean来停止线程的方法。分享给大家供大家参考,具体如下:packageThreads;/***Createdby
我们在使用ExecutorService的时候知道,在ExecutorService中有个一个Queue来保存提交的任务,通过不同的构造函数,我们可以创建无界的