简体   繁体   中英

ScheduledExecutorService and Shutdown Hook

When I use a ScheduledExecutorService (or ExecutorService) and submit a Runnable, my shutdown hook never gets called. 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. Any idea why?

From the javadoc of Runtime#addShutdownHook(Thread) :

The Java virtual machine shuts down in response to two kinds of events:

  • The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked , or
  • 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. *

As you said yourself, the threads in the Executor returned by newSingleThreadScheduledExecutor are not daemon threads. 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. The shutdown hook will run after the Executor has terminated.

* Assuming you aren't trying to send a user interrupt to your java process.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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