System.exit()之后JVM和主线程仍在运行

时间:2017-07-20 12:19:14

标签: java threadpoolexecutor

我需要在ThreadPoolExecutor完成当前正在执行的任务后完全关闭应用程序。为此,我添加了以下代码:

private void stopAppGracefully()
{
    MyApplication.executor.shutdown();

    System.exit(0);

    Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {

        logger.debug("Called the addShutdownHook()");

        //Wait infinitely till executor shut down
        while(!MyApplication.executor.isTerminated())
        {
          continue;
        }

        int queued = MyApplication.executor.getQueue().size();
        int active = MyApplication.executor.getActiveCount();
        int notCompleted = queued + active; // approximate

        long submitted = MyApplication.executor.getTaskCount();
        long completed = MyApplication.executor.getCompletedTaskCount();
        long notCompleted2 = submitted - completed; // approximate

        logger.debug("App is down..queued...:"+queued);
        logger.debug("App is down..active...:"+active);
        logger.debug("App is down..queued + active...:"+notCompleted);

        logger.debug("App is down..submitted...:"+submitted);
        logger.debug("App  is down..completed...:"+completed);
        logger.debug("App is down..submitted - completed...:"+notCompleted2);

        System.gc();

        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
        Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]);

        for (int i = 0; i < threadArray.length; i++)
        {
          logger.debug("Remaining threads: "+ threadArray[i].getName());
        }
      }
    });
}

但我在日志中看到以下信息:

20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 292 - App is down..queued...:0
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 293 - App is down..active...:0
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 294 - App is down..queued + active...:0
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 296 - App is down..submitted...:43
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 297 - App is down..completed...:43
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 298 - App is down..submitted - completed...:0
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Finalizer
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Reference Handler
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Thread-3
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Thread-2
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Thread-1
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: main
20 Jul 2017 05:03:17 DEBUG | ApplicationDirectoryWatcher | run | 307 - Remaining threads: Signal Dispatcher

仍有七个线程处于活动状态。 如何杀死/阻止这些线程?

我需要停止/杀死属于该应用程序的所有线程。

3 个答案:

答案 0 :(得分:2)

ExecutorService.shutdown()不会立即终止所有正在运行的任务并停止所有线程。它将继续运行当前正在运行的任务。请注意shutdown()不等待 - 它立即返回,当前任务可能仍在运行。

您可以调用awaitTermination(...)等待当前正在运行的任务完成,或者shutdownNow()确实会尝试杀死所有当前正在运行的任务。

要尝试正常关闭ExecutorService,然后强行关闭// Initiate graceful shutdown executorService.shutdown(); try { // Wait one minute for tasks to finish boolean terminated = executorService.awaitTermination(1L, TimeUnit.MINUTES); if (!terminated) { // If not terminated after one minute, shutdown forcefully executorService.shutdownNow(); } } catch (InterruptedException e) { System.err.println("Interrupted while awaiting termination"); } ,如果它在一定时间内没有停止,您可以使用以下内容:

{{1}}

答案 1 :(得分:0)

在Linux上,您可以将kill -9与PID一起使用。在Windows上,转到任务管理器和end task

enter image description here

答案 2 :(得分:0)

从Java文档中我们看到System.exit( int )方法基本上与手动调用Runtime.getRuntime().exit( int )方法的工作相同。然后,再看一下addShutdownHook( Thread )方法的Java文档。引用:

一旦关闭序列开始,就无法注册新的关闭挂钩或取消注册先前注册的挂钩。尝试这些操作中的任何一个都会导致抛出IllegalStateException。

读完这篇文章之后,您可能会遇到同步错误,其中VM在执行System.exit( int )方法时开始准备暂停阶段,但在实际关闭序列开始之前,addShutdownHook( Thread )行已执行。结果是它告诉你有线程正在运行,因为它们是有效的,因为VM还没有完全关闭。