我有一个预定的Executor服务设置,如
<div class="btn-group pull-right" data-toggle="buttons" style="top:26px;z-index:2;">
<label class="make-small btn btn-default" id="first_button_func">
<span>First Button</span>
</label>
<label class="make-small filter-column btn btn-default active">
<input type="checkbox" autocomplete="off" checked=""> <span>Second Button</span>
</label>
</div>
要停止此线程,我调用close方法,但线程通常不会停止。我不确定是什么错,如果我不知道我应该在我的run()代码中处理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);
}
}
}
。
答案 0 :(得分:1)
来自shutdownNow()
的javadoc:
除了尽力尝试停止处理主动执行任务之外,没有任何保证。例如,典型的实现将通过Thread.interrupt取消,因此任何无法响应中断的任务可能永远不会终止。
根据经验,线程确实会被打断,但根据此文档,即使这样也无法保证。
但是,您的任务不是您自己控制的,而是在scheduleWithFixedDelay()
内创建的私人任务。
来自scheduleWithFixedDelay()
的javadoc:
如果任务的任何执行遇到异常,则后续执行被禁止。 否则,任务只会通过取消或终止执行人来终止。
这意味着shutdownNow()
不会停止该线程。取消部分对我来说有点不清楚,因为Runnable
而不是Future
,没有cancel()
方法。任务停止的另一个原因是终止执行程序,但是只有在任务停止时才会终止池。
真正的解决方案潜伏在ScheduledThreadPoolExecutor
默认情况下,此类已取消的任务不会自动从工作队列中删除,直到其延迟结束。虽然这可以进一步检查和监控,但它也可能导致取消任务的无限制保留。要避免这种情况,请将setRemoveOnCancelPolicy设置为true,这会导致在取消时立即从工作队列中删除任务。
当您命令执行程序停止时,它会设置中断的标志,如果它是ScheduledThreadPoolExecutor
,则在removeOnCancelPolicy
为真时删除任务。
解决方案:
executor.setRemoveOnCancelPolicy(true)
。 [编辑]: 由于您使用的是工厂方法,因此无法直接实现。
进行以下更改:
private final ScheduledThreadPoolExecutor executor;
executor = new ScheduledThreadPoolExecutor(1, (runnable) -> {