正在学习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文档中查找此方法:
尝试停止所有正在执行的任务,暂停正在等待的任务的处理,并返回正在等待执行的任务的列表。
此方法不等待主动执行的任务终止。使用awaitTermination可以做到这一点。
除了尽力而为后,无法保证停止处理正在执行的任务。例如,典型的实现将通过Thread.interrupt取消,因此任何无法响应中断的任务都可能永远不会终止。
所以理想情况下,我期望的是在指定的超时后,我将收到一个Timeout异常,然后ExecutorService将强制关闭,但不会发生。
看过Java文档-似乎确实不能保证它会关闭。
如果不能保证,应该避免吗?
答案 0 :(得分:2)
看过Java文档-似乎确实不能保证它会关闭。
正确。
如果不能保证,应该避免吗?
不。
您实际上应该做的是使用ExecutorService
来避免或解决这些限制;例如
执行所有可能会长时间运行且应该可终止的任务,以便它们能够正确处理中断。如果操作正确,则ExecutorService
将终止。
不依赖于实际关闭的ExecutorService
。例如,您可以安排在应用程序需要关闭时执行以下操作:
shutdownNow()
awaitTermination(...)
ExecutorService
没有终止,那么它将调用System.exit(...)
终止应用程序。将ExecutorService
配置为将工作线程创建为守护程序线程;参见Turning an ExecutorService to daemon in Java。
守护程序线程不会阻止JVM退出。但请注意,您需要小心。如果所有非守护程序线程均已完成,则JVM将拔出插件,而不会中断ExecutorService
当前正在运行的任何任务。