ExecutorService 关闭挂钩

9

我有一个控制台应用程序,其中包含以下线程代码。当我按下Ctrl+C终止时,它似乎无法检测到控制键,我必须关闭命令提示窗口。

有什么线索可以说明为什么它无法检测到ctrl+c?

            final ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize);
        final long SHUTDOWN_TIME = TimeUnit.SECONDS.toMillis(10);
        for (int i = 0; i < threadPoolSize; i++) {
            executor.submit(new MessageWorker(topicSubscriber));
        }
        //--
        //Add JVM shutdown hook
        Runtime.getRuntime().addShutdownHook(new Thread() {
            /**
             * @see java.lang.Thread#run()
             */
            @Override
            public void run() {
                executor.shutdown();
                try {
                    if (!executor.awaitTermination(SHUTDOWN_TIME, TimeUnit.SECONDS)) {
                        log.warn("Executor did not terminate in the specified time.");
                        List<Runnable> droppedTasks = executor.shutdownNow();
                        log.warn("Executor was abruptly shut down. " + droppedTasks.size() + " tasks will not be executed.");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

实际上会发生什么?程序退出了,但是钩子没有被调用吗? - Nikolay Kuznetsov
程序就是无法停止。 - gpa
你在同一控制台中按下Ctrl+C了吗?这与钩子无关,它是其他问题。 - Nikolay Kuznetsov
我相信当在控制台上按下Ctrl+C键时,它会向JVM发送SIGINT信号,中断线程...这反过来又会调用关闭挂钩(shutdown hook)? - gpa
本来就应该是这样的。但即使你没有钩子,当接收到Ctrl+C时JVM也应该停止。钩子只是允许您进行额外的清理工作。 - Nikolay Kuznetsov
显示剩余2条评论
1个回答

8

仅从代码中猜测,看起来您的关闭时间设置为10,000秒,因此我不会惊讶您认为它没有退出!

    final long SHUTDOWN_TIME = TimeUnit.SECONDS.toMillis(10);
    ...
    if (!executor.awaitTermination(SHUTDOWN_TIME, TimeUnit.SECONDS)) {

哇,即使收到Ctrl+C,也可以延迟终止这么长时间吗? - Nikolay Kuznetsov
1
大多数信号(TERM、HUP、CUSTOM等)实际上都可以完全阻止,但这样做的危险在于调用者可能选择发送您无法阻止的信号(如KILL等)。 - SplinterReality

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接