如何正确closuresjava的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(); 

所有任务完成后(DONE或TIMEOUT-ed),我尝试closures执行程序,但不会停止: exec.isTerminated() = FALSE. 我怀疑有些任务是高兴的没有正确终止。

是的,我知道执行者的关机不保证任何事情:

尽最大努力试图停止处理主动执行的任务,没有任何保证。 例如,典型的实现将通过{@link Thread#interrupt}来取消,所以任何不能响应中断的任务都不会终止。

我的问题是,有没有办法确保这些(任务)线程将终止? 我想到的最好的解决scheme是在我的程序结束时调用System.exit() ,但那简直是愚蠢的。

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

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

当抛出InterruptedException时,线程上的中断标志需要重置,否则线程不会退出。 在这里看到更多的信息 。

不幸的是,你可能正在使用一个不服从这个的库,在这种情况下你不能轻易地绕过这个。 在这种情况下,一个重要的选项是分离一个subprocess来执行Callable的工作,并且在进程退出时清除所有的资源。 重量级和可能不平凡,但可靠。

从ExecutorService的 oracle文档页面推荐的方法:

  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)) 

 while (!pool.awaitTermination(60, TimeUnit.SECONDS)) 

关机 :

启动先前提交的任务被执行的有序closures,但不接受新的任务。

shutdownNow :

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

awaitTermination

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