为什么我的主方法中的shutdownhook没有被调用?

3

我在主方法中有以下内容:

public static void main(String[] args) throws IOException {
    Properties properties = getConfig();
    Jedis jedis = configure(properties)

    jedis.subscribe(queueHandler, "queue");

    Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            logger.debug("SHUTTING DOWN");
            jedis.close();
        }
    });
}

我注意到我的关闭挂钩中的代码从未运行,这是为什么?如何清理主方法持有的资源?


如何检查你的关闭钩子是否已经运行?如果在你之前的另一个关闭钩子中关闭了日志记录器,那么它可能无法记录你的消息。 - undefined
我认为你的代码中需要加入System.exit,以便执行关闭挂钩。 - undefined
3个回答

2
注意,subscribe是一个阻塞操作...(来自高级用法wiki)。
这意味着只有在取消订阅或关闭Jedis之后,关闭挂钩才会注册,并且您可能仅在JVM已经关闭时才到达代码的那部分(在这种情况下,新添加的关闭挂钩被忽略:关闭挂钩必须在JVM关闭之前注册)。
“有关更多使用示例,请查看测试。”(来自主Github页面
所以让我们看看PublishSubscribeCommandsTest
测试只是一个订阅操作,但在订阅操作中,当它接收到特定消息时,JedisPubSub将取消订阅自己,从而解除阻塞,以便测试可以完成。
您可以尝试的两件事:
  • 在调用jedis.subscribe之前注册关机挂钩
  • 从测试中复制代码并修改,以便您可以尝试阻塞和解除阻塞线程,并在关机挂钩中关闭Jedis(以清理已使用的资源)

0

主方法的正常退出与显式调用System.exit(0);有些不同

所以,请尝试以下操作:

public static void main(String[] args) throws IOException {
    //all your code...
    System.exit(0); //NOTE: non zero status will work different!
}

0

如果JVM关闭,关闭挂钩将被调用。确保程序退出。如果Jedis在后台运行(在一个线程中),即使执行了最后一条语句,关闭挂钩也不会被调用。在这种情况下,您必须停止该线程。最好的方法是尝试jedis.shutdown();(在添加关闭挂钩之后,作为最后一条语句)来关闭它。


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