繁体   English   中英

ScheduledExecutorService和Shutdown Hook

[英]ScheduledExecutorService and Shutdown Hook

当我使用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);
  }
}

由于执行者的线程不是守护进程,因此我希望可以调用shutdown钩子,但事实并非如此。 知道为什么吗?

Runtime#addShutdownHook(Thread)的javadoc中:

Java虚拟机将响应以下两种事件而关闭:

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

就像您自己说的那样, newSingleThreadScheduledExecutor返回的Executor的线程不是守护程序线程。 因此,它们必须先退出,然后才能调用您的关闭挂钩。

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

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

如果您绝对需要在任务运行后关闭执行程序,则可以执行以下操作:

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