简体   繁体   English

ScheduledExecutorService和Shutdown Hook

[英]ScheduledExecutorService and Shutdown Hook

When I use a ScheduledExecutorService (or ExecutorService) and submit a Runnable, my shutdown hook never gets called. 当我使用ScheduledExecutorService (或ExecutorService)并提交Runnable时,我的关闭挂钩永远不会被调用。 Ex, this program hangs: 例如,该程序挂起:

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);
  }
}

Since the executor's thread is not a daemon, I would expect the shutdown hook to be called, but it's not. 由于执行者的线程不是守护进程,因此我希望可以调用shutdown钩子,但事实并非如此。 Any idea why? 知道为什么吗?

From the javadoc of Runtime#addShutdownHook(Thread) : Runtime#addShutdownHook(Thread)的javadoc中:

The Java virtual machine shuts down in response to two kinds of events: Java虚拟机将响应以下两种事件而关闭:

  • The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked , or 当最后一个非守护程序线程退出时 ,或者调用exit(等效于System.exit)方法时,程序将正常退出 ,或者
  • The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown. 响应于用户中断(例如键入^ C)或系统范围的事件(例如用户注销或系统关闭)来终止虚拟机。 * *

As you said yourself, the threads in the Executor returned by newSingleThreadScheduledExecutor are not daemon threads. 就像您自己说的那样, newSingleThreadScheduledExecutor返回的Executor的线程不是守护程序线程。 So they must exit before your shutdown hook can be invoked. 因此,它们必须先退出,然后才能调用您的关闭挂钩。

You're doing things backwards. 你正在倒退。 You need to shutdown your Executor from some other part of your program's execution, not the shutdown hook. 您需要关闭您的Executor从你的程序的执行,而不是关闭挂钩的其他部分。 The shutdown hook will run after the Executor has terminated. Executor终止后,关闭挂钩将运行。

* Assuming you aren't trying to send a user interrupt to your java process. *假设您不尝试向java进程发送用户中断。

In the event you absolutely need to shutdown the executor after the task has run you can implement something like this: 如果您绝对需要在任务运行后关闭执行程序,则可以执行以下操作:

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM