Java使用ExecutorService来停止线程服务

网友投稿 342 2022-12-10


Java使用ExecutorService来停止线程服务

使用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

http:// 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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spring RedirectAttributes参数跳转代码实例
下一篇:Java集合Map的clear与new Map区别详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~