Java executorService.shutdownNow()不';不要停止线程
我有一个计划执行器服务设置,如Java executorService.shutdownNow()不';不要停止线程,java,multithreading,scheduledexecutorservice,Java,Multithreading,Scheduledexecutorservice,我有一个计划执行器服务设置,如 class Test { private final ScheduledExecutorService executor; public Test() { executor = Executors.newSingleThreadScheduledExecutor((runnable) -> { Thread thread = new Thread(runnable, this.getClass().ge
class Test {
private final ScheduledExecutorService executor;
public Test() {
executor = Executors.newSingleThreadScheduledExecutor((runnable) -> {
Thread thread = new Thread(runnable, this.getClass().getName());
thread.setDaemon(true);
return thread;
});
executor.scheduleWithFixedDelay(
new TestRefreshTask(), 0, 50000, TimeUnit.MILLISECONDS
);
}
private class TestRefreshTask implements Runnable {
@Override
public void run() {
//refresh some data
refreshdata();
}
}
public void close() {
executor.shutdown();
try {
if(!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
executor.awaitTermination(60, TimeUnit.SECONDS));
}
} catch (InterruptedException e) {
//Retry to dispose task
executor.shutdownNow();
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
}
要停止这个线程,我调用close方法,但线程通常不会停止。我不确定出了什么问题,也不确定我是否应该在run()代码中处理InterruptedException
- 线下的真正解决方案。本部分仅描述陷阱
shutdownNow()的javadoc中:
除了尽最大努力尝试停止处理积极执行的任务之外,没有其他保证。例如,典型的实现将通过Thread.interrupt取消,因此任何未能响应中断的任务可能永远不会终止
根据经验,线程确实会被中断,但根据本文档,即使这样也不能保证
但是,您的任务不是由您自己控制的,它是在scheduleWithFixedDelay()中创建的私有任务
从scheduleWithFixedDelay()的javadoc中:
如果任务的任何执行遇到异常,则会抑制后续执行否则,任务将仅通过取消或终止执行者而终止。
这意味着shutdownNow()
不会停止线程。取消部分对我来说有点不清楚,因为Runnable
与Future
相反,没有cancel()
方法。任务将停止的另一个原因是执行器的终止,但是池仅在任务停止时终止
真正的解决方案隐藏在ScheduledThreadPoolExecutor
的javadoc中:
默认情况下,此类已取消的任务不会自动从工作队列中删除,直到其延迟消失。虽然这可以进行进一步的检查和监视,但也可能会导致取消任务的无限保留。要避免这种情况,请将setRemoveOnCancelPolicy设置为true,这将导致在取消任务时立即从工作队列中删除任务
当您命令执行器停止时,它会设置中断标志,如果它是ScheduledThreadPoolExecutor
,则在removeOnCancelPolicy
为true时删除任务
解决方案:
- 在提交计划之前执行
executor.setRemoveOnCancelPolicy(true)
。
[编辑]:
由于使用工厂方法,因此无法直接实现
进行以下更改:
私有最终调度线程池执行器执行器代码>
executor=newscheduledthreadpoolexecutor(1,(runnable)->{
“除了尽最大努力停止处理正在执行的任务外,没有其他保证。例如,典型的实现将通过Thread.interrupt()取消,因此任何无法响应中断的任务可能永远不会终止。”-同样来自:你等待终止60秒。你知道refreshdata平均需要多长时间吗?你使用的是什么版本的Java?@JohnVint我使用的是Java 1.8。Refresh做了很多事情,但通常只需要不到60秒。这一点很好。因为我在服务器和本地运行此代码。rem上的代码这台机器似乎更经常出故障