关机挂钩未杀死执行器



我有以下代码:

public class Driver {
    private ExecutorService executor = Executors.newCachedThreadPool();
    public static void main(String[] args) {
        Driver d = new Driver();
        d.run();
    }
    private void run() {
        final Timer timer = new Timer();
        final TimerTask task = new TimerTask() {
            @Override
            public void run() {
                System.out.println("Task is running!");
            }
        };
        Runnable worker = new Runnable() {
            @Override
            public void run() {
                timer.scheduleAtFixedRate(task, new Date(), 5 * 1000);
            }
        };
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                System.out.println("Shutdown hook is being invoked!");
                try {
                    if(executor.awaitTermination(20, TimeUnit.SECONDS))
                        System.out.println("All workers shutdown properly.");
                    else {
                        System.out.println(String.format("Maximum time limit of %s reached " +
                                "when trying to shut down workers. Forcing shutdown.", 20));
                        executor.shutdownNow();
                    }
                } catch (InterruptedException interrupt) {
                    System.out.println("Shutdown hook interrupted by exception: " +
                            interrupt.getMessage());
                }
                System.out.println("Shutdown hook is finished!");
            }
        });
        executor.submit(worker);
        System.out.println("Initializing shutdown...");
    }
}

当它运行时,我得到以下控制台输出:

Initializing shutdown...
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
... (this keeps going non-stop)

当我运行这个程序时,应用程序永远不会终止。相反,每隔5秒钟,我就会看到一个新的print ln"Task is running!"。我本来期望主线程到达main方法的末尾,打印"正在初始化关机…",调用添加的关机挂钩,杀死执行器,最后打印出"关机挂钩完成了!"。

相反,"任务正在运行"只是不断地被打印出来,程序永远不会终止。这是怎么回事?

我不是专家,但AFAIK您必须终止所有非守护程序线程,以便关闭挂钩"启动"。在最初的示例中,您有3个非守护程序:

  1. "Main"的线程——这是你在这里想要的唯一非精灵
  2. 运行"TimerTask"的线程——它是由"Timer"创建的,您通过修复到Timer(true)来覆盖它
  3. 运行"worker"的线程-它由"executor"创建,为了让"executo器"创建守护程序线程,您应该创建ThreadFactory。(至少这是我知道的方式;可能还有其他方式…)

因此,我认为您应该创建一个ThreadFactory,并在初始化"executor"时使用它。

创建一个类,该类将成为ThreadFactory:

private class WorkerThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r, "Worker");
        t.setDaemon(true);
        return t;
    }
}

--重要的线路当然是setDaemon:)

将其实例作为参数传递给newCachedThreadPool方法:

private ExecutorService executor = Executors.newCachedThreadPool(new WorkerThreadFactory());

应用这两个变化对我来说很有用,我得到了:

Maximum time limit of 20 reached when trying to shut down workers. Forcing shutdown.
Shutdown hook is finished!

希望有帮助,
Izik

golan2@hotmail.com

它不会关闭,因为Timer()创建并启动了一个非守护进程线程。。。这样就永远不会停止。

有两件事会导致JVM自动关闭:

  • System.exit()(或Runtime.halt())的调用
  • 最后一个剩余的非守护进程线程的终止

由于您已经创建了第二个非守护进程线程(除了运行main()的线程之外),因此第二个条件将不满足。

最新更新