Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程和关闭钩子_Java_Multithreading_Sigint_Shutdown Hook - Fatal编程技术网

Java线程和关闭钩子

Java线程和关闭钩子,java,multithreading,sigint,shutdown-hook,Java,Multithreading,Sigint,Shutdown Hook,我刚刚遇到一个有趣的问题。在Java中,如果一个线程调用System.exit(),那么它就不能通过thread.join()进行连接 这给我带来了一些问题,因为我想在应用程序运行后使用关机挂钩进行清理,例如: Runtime.getRuntime.addShutdownHook(new Thread() { public void run() { reader.join(); writer.join(); in.close();

我刚刚遇到一个有趣的问题。在Java中,如果一个线程调用
System.exit()
,那么它就不能通过
thread.join()
进行连接

这给我带来了一些问题,因为我想在应用程序运行后使用关机挂钩进行清理,例如:

Runtime.getRuntime.addShutdownHook(new Thread() {
    public void run() {
        reader.join();
        writer.join();
        in.close();
        out.close();
    }
});
其思想是,在关闭这些资源之前,它确保线程已经使用完各自的资源。问题是有三种情况可以调用关闭挂钩。它们是:

  • 用户点击[ctrl]+[C]
  • 读卡器线程完成,并调用
    System.exit()
  • 编写器线程完成,并调用
    System.exit()
  • 第一种情况下,用户点击[ctrl]+[C]可以正常工作。但在其他两种情况中,关闭挂钩都会永远阻塞。这是一个连锁反应,一个
    Thread.join()
    ,它是针对一个已经调用了
    System.exit()
    的线程调用的,永远阻塞


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

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

    系统。如果successful即使抛出异常也没有返回,则退出
    ,因此线程将永远不会完成。在关闭挂钩之前,这不是一个问题


    解决方法是使用普通的标准锁(或者干脆用
    新线程(new Runnable(){public void run(){System.exit(0);}}).start();
    )。

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

    当在java.util.concurrent中使用执行器和其他东西时,您可以简单地调用shutdown并等待它终止、指定超时等,这样会更加健壮。如果您使用的是Java1.7,请使用TrywithResources关闭您的流。这样,除了关闭遗嘱执行人之外,你没有太多的清理工作要做。如果不是,则使用finally块。不要在最后一个区块之外的任何地方调用close。

    您所做的是:

    关机挂钩也应该很快完成工作

    连接随机线程不能称为“快速”


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

    为什么不尝试避免调用
    System.exit()
    ,而是安排适当的清理,让JVM自然退出?还要注意“If
    System.exit()
    是在虚拟机开始其关闭序列后调用的,如果正在运行关闭挂钩,则此方法将无限期阻止。“-是否有可能调用
    System.exit()
    两次?谢谢你的答复。抱歉,为了尽量使我的问题简明扼要,我显然遗漏了很多代码。实际上,在调用
    Thead.join()
    s之前,我首先对线程调用一个方法,告诉它们应该尽快完成。不幸的是,线程没有独立的资源。因此,他们不能关闭自己的资源,以防其他线程仍在使用它们。