如何正确关闭java ExecutorService

时间:2016-04-15 09:59:39

标签: java multithreading executorservice shutdown

我有一个简单的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();

完成所有任务(DONE或TIMEOUT-ed)后,我尝试关闭执行程序,但它不会停止:exec.isTerminated() = FALSE. 我怀疑某些被计时的任务没有被正确终止。

是的,我知道遗嘱执行人的关闭并不保证任何事情:

  

除了努力尝试停止之外,没有任何保证         处理积极执行的任务。例如,典型的         实现将通过{@link Thread#interrupt}取消,所以任何        无法响应中断的任务可能永远不会终止。

我的问题是,有没有办法确保这些(任务)线程终止? 我提出的最佳解决方案是在程序结束时调用System.exit(),但这很愚蠢。

2 个答案:

答案 0 :(得分:11)

来自enter image description here的Oracle API文档页面的推荐方法:

private void xrPictureBox1_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
    xrPictureBox1.ImageUrl = @"\\10.10.101.186\photo\" + Report.GetCurrentColumnValue("APPLICANT_PHOTO");
}

如果您的游戏池需要更长时间才能关闭,则可以更改

 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();
   }

1f (!pool.awaitTermination(60, TimeUnit.SECONDS))

关闭相关方法的简要概述

ExecutorService

  

启动有序关闭,其中执行先前提交的任务,但不接受任何新任务。

shutdown()

  

尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表。

shutdownNow()

  

阻止所有任务在关闭请求之后完成执行,或发生超时,或者当前线程被中断,以先发生者为准。

答案 1 :(得分:5)

你能掌控这些任务吗?即你自己创造这些?我怀疑那些线程中断被忽略的地方,例如。

try {
  ....
}
catch {InterruptedException e) {
   // do nothing
}

当抛出InterruptedException时,需要重置线程上的中断标志,否则线程将不会退出。见here for more info

不幸的是,您可能正在使用不遵守此规则的库,在这种情况下,您无法轻易绕过这一点。在这种情况下,一个重量级选项是分叉子进程以执行Callable的作业,这将在进程退出时清除所有资源。重量级的,可能是非平凡的,但可靠的。