【问题标题】:ScheduledExecutorService and Shutdown HookScheduledExecutorService 和 Shutdown Hook
【发布时间】:2015-10-07 00:51:25
【问题描述】:

当我使用 ScheduledExecutorService(或 ExecutorService)并提交 Runnable 时,我的关闭挂钩永远不会被调用。例如,这个程序挂起:

public class App {
  static ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();

  static {
    Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {
        exec.shutdownNow();
      }
    });
  }

  public static void main(String[] args) {
    exec.schedule(new Runnable() {
      @Override
      public void run() {
      }
    }, 10, TimeUnit.SECONDS);
  }
}

由于执行程序的线程不是守护程序,我希望调用关闭挂钩,但事实并非如此。知道为什么吗?

【问题讨论】:

  • 您认为为什么会调用关闭挂钩?
  • 我不希望调用关闭挂钩,但事实并非如此。这不是你所期望的吗?
  • @SotiriosDelimanolis 我编辑了他的问题,因为我认为这是一个错字。
  • 由于执行器的线程不是守护进程 如果它不是守护进程,它必须在VM退出之前完成。
  • 你应该在某个地方明确地调用shutdownNow(),而不是通过钩子。

标签: java executorservice scheduledexecutorservice


【解决方案1】:

来自Runtime#addShutdownHook(Thread)的javadoc:

Java 虚拟机响应两种情况而关闭 事件:

  • 程序正常退出,当最后一个非守护线程退出或调用exit(相当于System.exit)方法时,或
  • 虚拟机被终止以响应用户中断,例如键入 ^C,或系统范围的事件,例如用户注销或 系统关闭。*

正如您自己所说,newSingleThreadScheduledExecutor 返回的Executor 中的线程不是守护线程。所以它们必须在你的关闭钩子被调用之前退出。

你做事倒退了。您需要从程序执行的其他部分关闭Executor,而不是关闭钩子。关闭挂钩将在Executor 终止后运行。

* 假设您没有尝试向您的java 进程发送用户中断。

【讨论】:

    【解决方案2】:

    如果您在任务运行后绝对需要关闭执行器,您可以实现如下所示:

    static {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                Logger.getGlobal().info("destroying");
                exec.shutdownNow();
            }
        });
    }
    
    public static void main(String[] args) throws Exception {
        Future f = exec.schedule(new Runnable() {
            @Override
            public void run() {
                Logger.getGlobal().info("thread run");
    
            }
        }, 10, TimeUnit.SECONDS);
        while (!f.isDone()) {
            Logger.getGlobal().info("waiting for task to finish");
            Thread.sleep(1000);
        }
        Runtime.getRuntime().exit(0);
    }
    

    【讨论】:

      猜你喜欢
      • 2018-09-23
      • 1970-01-01
      • 1970-01-01
      • 2012-08-04
      • 2022-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多