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

时间:2016-04-02 05:10:48

标签: java redis jedis

我的主要方法中有以下内容:

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

我注意到我的shutdown hook中的代码永远不会运行,为什么呢?如何清理主方法所拥有的资源?

3 个答案:

答案 0 :(得分:1)

“请注意,订阅是阻止操作......”(来自the AdvancedUsage wiki)。

这反过来意味着只有在取消订阅或关闭Jedis后才会注册shutdown-hook, 并且您可能只在JVM已经关闭时才到达代码的那一部分 (在这种情况下,将忽略新添加的关闭挂钩:必须在JVM关闭之前注册关闭挂钩)。

“有关更多用法示例,请检查测试。” (来自main Github page

让我们看一下PublishSubscribeCommandsTest
测试只是一个订阅操作,但在订阅操作中,MoveNotPossibleException in Move.php line 198: A new node cannot be moved. 在收到特定消息时取消订阅,从而解锁自身以便测试完成。

您可以尝试的两件事:

  • 在致电JedisPubSub
  • 之前注册关闭钩子
  • 从测试中复制代码并对其进行修改,以便您可以尝试阻止和解除阻塞线程,并在关闭钩子中关闭Jedis(以清理使用过的资源)

答案 1 :(得分:0)

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

答案 2 :(得分:0)

Main-Method的常规退出与显式调用System.exit(0);

略有不同

所以,试试以下:

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