ExecutorService shutdownNow现在不关闭JVM

时间:2019-06-23 03:05:47

标签: java multithreading executorservice

正在学习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文档-似乎确实不能保证它会关闭。

如果不能保证,应该避免吗?

1 个答案:

答案 0 :(得分:2)

  

看过Java文档-似乎确实不能保证它会关闭。

正确。

  

如果不能保证,应该避免吗?

不。

您实际上应该做的是使用ExecutorService来避免或解决这些限制;例如

  • 执行所有可能会长时间运行且应该可终止的任务,以便它们能够正确处理中断。如果操作正确,则ExecutorService将终止。

  • 不依赖于实际关闭的ExecutorService。例如,您可以安排在应用程序需要关闭时执行以下操作:

    1. 它呼叫shutdownNow()
    2. 它会在适当的超时时间内调用awaitTermination(...)
    3. 如果ExecutorService没有终止,那么它将调用System.exit(...)终止应用程序。
  • ExecutorService配置为将工作线程创建为守护程序线程;参见Turning an ExecutorService to daemon in Java

    守护程序线程不会阻止JVM退出。但请注意,您需要小心。如果所有非守护程序线程均已完成,则JVM将拔出插件,而不会中断ExecutorService当前正在运行的任何任务。