[英]How to properly shutdown java ExecutorService
I have a simple java ExecutorService
that runs some task objects (implements Callable
).我有一个简单的 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();
After all tasks are finished (either DONE or TIMEOUT-ed), I try to shutdown the executor, but it wont stop: exec.isTerminated() = FALSE.
在所有任务完成后(完成或超时),我尝试关闭执行程序,但它不会停止:
exec.isTerminated() = FALSE.
I suspect that some tasks that are timeouted are not properly terminated.我怀疑某些超时的任务没有正确终止。
And yes, I know that executor's shutdown is not guaranteing anything:是的,我知道 executor 的关闭并不能保证任何事情:
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks.
除了尽力尝试停止处理正在执行的任务之外,没有任何保证。 For example, typical implementations will cancel via {@link Thread#interrupt}, so any task that fails to respond to interrupts may never terminate.
例如,典型的实现将通过 {@link Thread#interrupt} 取消,因此任何未能响应中断的任务可能永远不会终止。
My question is, is there a way to ensure those (task) threads will terminate?我的问题是,有没有办法确保那些(任务)线程会终止? The best solution I came up with, is to call the
System.exit()
at the end of my program, but that is plain silly.我想出的最佳解决方案是在程序结束时调用
System.exit()
,但这很愚蠢。
Recommended way from Oracle API documentation page of ExecutorService :来自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();
}
If your pool is taking more time to shutdown, you can change如果您的池需要更多时间关闭,您可以更改
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
to到
while (!pool.awaitTermination(60, TimeUnit.SECONDS))
shutdown() : 关机() :
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
启动有序关闭,其中执行先前提交的任务,但不会接受新任务。
shutdownNow() : 关机现在() :
Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表。
awaitTermination(long timeout, TimeUnit unit) throws InterruptedException : awaitTermination(long timeout, TimeUnit unit) 抛出 InterruptedException :
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
阻塞直到所有任务在关闭请求后完成执行,或发生超时,或当前线程被中断,以先发生者为准。
Do you have control of those tasks ?你能控制这些任务吗? ie are you creating those yourself ?
即你自己创造那些? I suspect somewhere in those a thread interrupt is being ignored eg
我怀疑其中某个线程中断被忽略,例如
try {
....
}
catch {InterruptedException e) {
// do nothing
}
When an InterruptedException is thrown, the interrupt flag on the thread needs to be reset, otherwise the thread will not exit.当抛出 InterruptedException 时,需要重置线程上的中断标志,否则线程不会退出。 See here for more info .
请参阅此处了解更多信息。
Unfortunately you may be using a library that doesn't obey this, in which case you can't easily circumvent this.不幸的是,您可能正在使用不遵守此规定的库,在这种情况下,您无法轻松规避这一点。 In that case one heavyweight option is to fork off a sub process to perform the job of the
Callable
, and that will clear up all resources upon process exit.在这种情况下,一个重量级的选择是派生一个子进程来执行
Callable
的工作,这将在进程退出时清除所有资源。 Heavyweight and possibly non-trivial, but reliable.重量级,可能不平凡,但可靠。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.