Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.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_Sockets - Fatal编程技术网

Java:正确关闭多个线程

Java:正确关闭多个线程,java,multithreading,sockets,Java,Multithreading,Sockets,我正在制作一个简单的服务器,它将产生多个线程来处理多个客户端。我想知道在服务器终止时关闭和关闭所有流和线程的正确方法 我添加了一个shutdownHook,它运行一个告诉服务器关闭的方法。服务器依次将关闭调用广播到它已打开的所有线程,这会将每个线程中的“isClosed”布尔值设置为true 我所期望的是,每个线程在到达run()方法末尾并再次循环时,都会命中while(!isClosed)条件,从而通过关闭所有正确的套接字/流并返回来正确终止它们自己 但是,我不知道这是否会正确地关闭所有内容,

我正在制作一个简单的服务器,它将产生多个线程来处理多个客户端。我想知道在服务器终止时关闭和关闭所有流和线程的正确方法

我添加了一个shutdownHook,它运行一个告诉服务器关闭的方法。服务器依次将关闭调用广播到它已打开的所有线程,这会将每个线程中的“isClosed”布尔值设置为true

我所期望的是,每个线程在到达run()方法末尾并再次循环时,都会命中while(!isClosed)条件,从而通过关闭所有正确的套接字/流并返回来正确终止它们自己

但是,我不知道这是否会正确地关闭所有内容,因为程序应该在关闭钩子完成后终止。它完成得相当早,因为它所做的只是传播结束消息。这是否意味着某些线程没有足够的时间来正确关闭


如果是这样,最好的方法是让shutdownhook手动关闭每个线程,确保它们在返回之前已关闭?

使用
ExecutorService
是现代的方法。它从代码中去掉了很多微妙的部分


是一个很好的起点。

如果服务器终止,线程可能没有足够的时间正常终止,这是正确的。然而,这可能是一个问题,也可能不是一个问题,这取决于你试图做什么。如果不需要清理工作,那么您可能不需要担心,因为线程突然终止不会导致任何问题

但是,如果需要进行清理工作(例如写入数据库),那么您需要做其他事情。最好的方法(在Java中)是使用Executor/ExecutorService和相关项()。这些方法很好地解决了您的问题,而且您还获得了一些不错的免费赠品,比如线程池管理,这样扩展就容易多了。如果您为每个客户机生成一个新线程,那么在以后尝试扩展时会遇到很大的问题,例如,您不能每分钟创建一百万个线程


如果您习惯于使用原始线程,那么使用executor的东西是一种调整,但是值得研究。祝你好运

关闭钩子在循环中发生得太晚,这样做没有用处。它预计会很快完成,JVM已经在运行中,如果它们是守护进程,可能会占用现有的线程

我只需要在连接线程上设置一个读取超时,比如15-30秒。如果发生超时
(SocketTimeoutException)
,请关闭套接字并退出线程。当然,客户将不得不处理掉的连接,但他们已经这样做了。然后,当您想关闭时,只需停止接受新连接(例如关闭
ServerSocket
,并让其accept线程正确处理产生的异常)。当所有现有连接线程都退出时,JVM将退出,这实际上不应超过超时时间加上最长事务的长度。确保连接线程不是守护进程


如果您不介意客户端在事务进行到一半时被切断,只需调用
System.exit()。

您是否考虑过让您的线程成为守护线程。 只需添加t.setdaemon(true);在调用线程的start方法之前。 如果这些线程应该在程序结束时结束,那么一旦所有其他非守护进程线程结束,使它们成为守护进程将杀死它们。 线程池中使用的线程是应该是守护进程的线程的好例子。
我真的认为它对您很有用。

基本方法没有错,但您也可以研究
Thread.interrupt()
,以防线程中有任何阻塞调用。(请注意,并非所有此类调用都是可中断的——我相信常规套接字读取不是。)如果它们是非守护进程线程,那么JVM将不会退出,直到所有线程都从其run方法返回,不管是否已返回shutdownHook方法。使用executorservice管理线程,并在完成后关闭executorservice。非常感谢。ExecutorService似乎是实现这一点的正确方法。如果我理解这一点,我只需使用Executors工厂创建一个ExecutorService。然后我用execute添加线程,然后服务为我管理它?然后,为了关闭,我在关闭应用程序时结合使用shutdownNow和shutdownNow来清理线程?是的,您是对的。在构造线程时,您需要正确地处理InterruptedException,这样,如果它被抛出到您的线程上,就会进行正确的清理。捕获InterrupedException后不重新评估其终止条件的线程可能无法使用ExecutorService正常终止。如果要确保在退出应用程序之前终止已正常进行,可以在主线程中使用ExecutorService.isTerminated()或awaitTermination()轻松检查它们的状态。希望有帮助!