0

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

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

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

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

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

4

4 回答 4

0

shutdownHook 在循环中发生得太晚,无法以这种方式使用。预计它会很快完成,并且 JVM 已经处于关闭状态,如果它们是守护进程,它可能会占用现有线程。

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

如果您不介意客户在交易过程中被砍掉,请致电System.exit().

于 2013-02-14T04:33:39.923 回答
0

使用 anExecutorService是现代的做法。它从代码中消除了很多繁琐的部分。

是一个很好的起点。

于 2013-02-14T00:00:35.690 回答
0

您是正确的,如果服务器终止,线程可能没有足够的时间正确终止。但是,根据您要执行的操作,这可能是也可能不是问题。如果不需要清理工作,那么您可能不需要担心它,因为让线程突然终止不会导致任何问题。

但是,如果需要完成清理工作(例如写入数据库),那么您需要做一些其他的事情。最好的方法(在 Java 中)是使用 Executor/ExecutorService 和相关项目(http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/Executors.html)。这些可以很好地解决您的问题,另外您还可以获得一些不错的免费赠品,例如线程池管理,因此扩展更加容易。例如,如果您为每个客户端生成一个新线程,那么稍后尝试扩展时就会遇到大问题,因为您不能每分钟创建一百万个线程。

如果您习惯使用原始线程,则使用 E​​xecutor 的东西有点调整,但值得研究。祝你好运!

于 2013-02-14T00:04:07.653 回答
0

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

于 2013-02-14T12:29:32.820 回答