Java线程和关闭钩子
我刚刚遇到一个有趣的问题。在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();
System.exit()
,那么它就不能通过thread.join()
进行连接
这给我带来了一些问题,因为我想在应用程序运行后使用关机挂钩进行清理,例如:
Runtime.getRuntime.addShutdownHook(new Thread() {
public void run() {
reader.join();
writer.join();
in.close();
out.close();
}
});
其思想是,在关闭这些资源之前,它确保线程已经使用完各自的资源。问题是有三种情况可以调用关闭挂钩。它们是:
System.exit()
System.exit()
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自然退出?还要注意“IfSystem.exit()
是在虚拟机开始其关闭序列后调用的,如果正在运行关闭挂钩,则此方法将无限期阻止。“-是否有可能调用System.exit()
两次?谢谢你的答复。抱歉,为了尽量使我的问题简明扼要,我显然遗漏了很多代码。实际上,在调用Thead.join()
s之前,我首先对线程调用一个方法,告诉它们应该尽快完成。不幸的是,线程没有独立的资源。因此,他们不能关闭自己的资源,以防其他线程仍在使用它们。