java 线程 shutdown_Java使用ExecutorService来停止线程服务

1d13be22bfe8df58aa785bd41cbab156.png

使用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 taskCancelledAtShutdown= Collections.synchronizedSet(new HashSet());

public TrackingExecutor(ExecutorService executorService){

this.executorService=executorService;

}

@Override

public void shutdown() {

executorService.shutdown();

}

@Override

public List 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 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 notrunList=trackingExecutor.shutdownNow();

if(trackingExecutor.awaitTermination(800, TimeUnit.SECONDS)){

List runButCancelledList= trackingExecutor.getCancelledTask();

}

}

trackingExecutor.shutdownNow()返回的是未执行的任务。而trackingExecutor.getCancelledTask()返回的是被取消的任务。

上面的任务其实还有一个缺点,因为我们在存储被取消的任务列表的额时候taskCancelledAtShutdown.add(command),因为之前的判断不是原子操作,则可能会产生误报。

本文的例子请参考https://github.com/ddean2009/learn-java-concurrency/tree/master/ExecutorServiceShutdown

到此这篇关于Java使用ExecutorService来停止线程服务的文章就介绍到这了,更多相关Java ExecutorService停止线程内容请搜索云海天教程以前的文章或继续浏览下面的相关文章希望大家以后多多支持云海天教程!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值