【问题标题】:Java Threads and Shutdown HookJava 线程和关闭挂钩
【发布时间】:2013-07-18 15:48:00
【问题描述】:

我刚刚遇到了一个有趣的问题。似乎,在 Java 中,如果一个线程调用System.exit(),则它不能通过Thread.join() 加入。

这引起了我的问题,因为我想在我的应用程序之后使用关闭挂钩进行清理,例如:

Runtime.getRuntime.addShutdownHook(new Thread() {
    public void run() {
        reader.join();
        writer.join();
        in.close();
        out.close();
    }
});

这个想法是确保线程在关闭这些资源之前已经完成了它们各自的资源。问题是有 3 种情况可以调用关闭挂钩。它们是:

  1. 用户点击 [ctrl] + [C]。
  2. Reader 线程完成,并调用System.exit()
  3. 编写器线程完成,并调用System.exit()

第一种情况,用户点击 [ctrl] + [C] 可以正常工作。但在其他两种情况下,关闭挂钩会永远阻塞。这是一个连锁效应,即一个 Thread.join()(针对已调用 System.exit() 的线程调用)永远阻塞。

因此,我有 2 个问题。首先,我知道我可以改用Thread.join(long millis),这样他们就不会无限期地阻塞,但是谁能想到一个更优雅的解决方案?其次,虽然可以对同一个线程调用Thread.join() 两次,而第二次它会立即返回,有没有人知道为什么对已经调用System.exit() 的线程调用Thread.join() 会无限期阻塞并且不会'不只是立即返回?

【问题讨论】:

  • 为什么不尽量避免调用System.exit(),而是安排适当的清理,让JVM自然退出?
  • 还要注意“如果System.exit()在虚拟机开始关机序列后被调用,那么如果关机钩子正在运行,这个方法将无限期地阻塞。” - 做你打电话给System.exit() 两次? (Reference)

标签: java multithreading sigint shutdown-hook


【解决方案1】:

System.exit 如果成功即使通过抛出异常也不会返回,因此线程永远不会完成。在关闭挂钩之前,这不是问题。

解决方法是使用通常的标准锁(或者甚至只是使用new Thread(new Runnable() { public void run() { System.exit(0); }}).start(); 破解它)。

【讨论】:

    【解决方案2】:

    你正在做的是specifically prohibited:

    关闭挂钩也应该快速完成它们的工作。

    加入随机线程不能被描述为“快速”。

    显然,这些线程在退出时应该关闭它们的自己的流。如果他们不退出,调用join() 将如何完成任何事情?

    【讨论】:

    • 感谢您的回复。抱歉,为了让我的问题简短明了,我显然省略了很多代码。实际上,在调用Thead.join()s 之前,我实际上首先针对线程调用了一个方法来告诉它们应该尽快完成。不幸的是,线程没有独立的资源。所以他们不能关闭自己的资源,以防其他线程仍在使用它们。
    【解决方案3】:

    不建议使用 System.exit() ,因为它只会终止 JVM。还有其他并发工具,例如 CountDownLatch。您甚至可以使用 finally 在关机时正确清理。

    【讨论】:

      【解决方案4】:

      使用执行器,不要使用连接或手动创建线程。

      当使用执行器和 java.util.concurrent 中的其他东西时,您可以简单地调用 shutdown 并等待它终止、指定超时等。更加健壮。如果您使用的是 java 1.7,请使用 try with resources 来关闭您的流。这样,除了关闭执行程序之外,您没有太多清理工作要做。如果没有,请使用 finally 块。永远不要在 finally 块之外的任何地方调用 close。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-20
        • 1970-01-01
        相关资源
        最近更新 更多