正在学习Java 1.5中引入的ExecutorService
以下示例似乎违背了预期的行为:
public static void main(String[] args) throws InterruptedException,
ExecutionException,TimeoutException {
Callable<String> task = () -> {
int counter = 0;
while(true) {
//infinite loop will never exit
if(counter == 7) {
break;
}
}
return "abc";
};
ExecutorService service = Executors.newSingleThreadExecutor();
try {
Future<String> future = service.submit(task);
System.out.println("result = " + future.get(10000,TimeUnit.MILLISECONDS));
}finally {
System.out.println("<<<< finally >>>>");
service.shutdownNow();
}
}
查看此方法的 java 文档:
尝试停止所有活动正在执行的任务,停止对等待任务的处理,并返回等待执行的任务的列表。
此方法不会等待主动执行的任务终止。使用 awaitTerminate 来执行此操作。
除了尽力尝试停止处理主动执行的任务之外,没有任何保证。例如,典型的实现将通过 Thread.break 取消,因此任何无法响应中断的任务都可能永远不会终止。
因此,理想情况下,我所期望的是,在指定的超时后,我将收到超时异常,然后执行器服务将强制关闭,但这不会发生。
查看了java文档 - 它似乎确实表明无法保证它会关闭。
如果不能保证,那么应该避免吗?
查看了java文档 - 它似乎确实表明无法保证它会关闭。
正确。
如果不能保证,那么应该避免吗?
不。
您实际上应该做的是以避免或绕过限制的方式使用ExecutorService
;例如
-
实现任何可能长时间运行且应可终止的任务,以便它们正确处理中断。 如果您正确执行此操作,那么您
ExecutorService
将终止。 -
不要依赖实际关闭
ExecutorService
。 例如,您可以安排当应用程序需要关闭时,它会执行以下操作:- 它调用
shutdownNow()
- 它使用适当的超时调用
awaitTermination(...)
- 如果
ExecutorService
未终止,则调用System.exit(...)
来终止应用程序。
- 它调用
-
配置
ExecutorService
以将工作线程创建为守护程序线程;请参阅在 Java 中将执行程序服务转换为守护程序。守护进程线程不会阻止 JVM 退出。 但请注意,您需要小心。 如果所有非守护进程线程都已完成,JVM 将拔掉插头,而不会中断
ExecutorService
当前正在运行的任何任务。