N10*_*N10 9 java multithreading shutdown executorservice
我有一个简单的java ExecutorService运行一些任务对象(实现Callable).
ExecutorService exec = Executors.newSingleThreadExecutor();
List<CallableTask> tasks = new ArrayList<>();
// ... create some tasks
for (CallableTask task : tasks) {
Future future = exec.submit(task);
result = (String) future.get(timeout, TimeUnit.SECONDS);
// TASKS load some classes and invoke their methods (they may create additional threads)
// ... catch interruptions and timeouts
}
exec.shutdownNow();
Run Code Online (Sandbox Code Playgroud)
在完成所有任务(DONE或TIMEOUT-ed)之后,我尝试关闭执行程序,但它不会停止:exec.isTerminated() = FALSE.
我怀疑某些被执行的任务未正确终止.
是的,我知道执行者的关闭不能保证任何事情:
除尽力尝试停止处理主动执行任务之外,没有任何保证.例如,典型的实现将通过{@link Thread#interrupt}取消,因此任何未能响应中断的任务都可能永远不会终止.
我的问题是,有没有办法确保这些(任务)线程终止?我提出的最佳解决方案是System.exit()在程序结束时调用,但这很简单.
Rav*_*abu 13
从ExecutorService的 Oracle API文档页面推荐的方法:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
Run Code Online (Sandbox Code Playgroud)
如果您的池有更多时间关闭,您可以更改
1f (!pool.awaitTermination(60, TimeUnit.SECONDS))
Run Code Online (Sandbox Code Playgroud)
至
while (!pool.awaitTermination(60, TimeUnit.SECONDS))
Run Code Online (Sandbox Code Playgroud)
启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务.
尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表.
awaitTermination(long timeout,TimeUnit unit)抛出InterruptedException:
阻止所有任务在关闭请求之后完成执行,或者发生超时,或者当前线程被中断,以先发生者为准.
你有控制这些任务吗?即你自己创造这些?我怀疑那些线程中断被忽略的地方,例如
try {
....
}
catch {InterruptedException e) {
// do nothing
}
Run Code Online (Sandbox Code Playgroud)
抛出InterruptedException时,需要重置线程上的中断标志,否则线程不会退出.见此处获得更多信息.
不幸的是,您可能正在使用不遵守此规定的库,在这种情况下,您无法轻易绕过这一点.在这种情况下,一个重量级选项是分叉一个子进程来执行该作业Callable,这将在进程退出时清除所有资源.重量级的,可能是非平凡的,但可靠的.
| 归档时间: |
|
| 查看次数: |
8073 次 |
| 最近记录: |