我有以下TCP客户端 - 服务器通信结构:
问题是如何优雅地停止整个系统?我可以通过关闭ServerSocket来停止接受器线程。它会导致accept()阻塞调用抛出SocketException。但是如何阻止工人呢?他们从流中读取并且此调用正在阻止。根据{{3}}流不会抛出InterruptedException,因此worker不能被中断()。
看起来我需要从另一个线程关闭工作套接字,对吧?为此,套接字应该是一个公共字段,或者应该在worker中提供一个方法来关闭它。这会不错?或者可能是我的整个设计存在缺陷?
答案 0 :(得分:3)
您的模型运作正常。中断IO等不可中断构造的最佳方法是关闭套接字。你当然可以在进入阻塞状态之前处理它,但是如果IO功能没有对中断作出反应你就没有很多好的选择
答案 1 :(得分:2)
我建议使用工作人员定期检查的布尔标志。调用标志shouldStop
,如果设置为true,则工作人员清理然后死亡。遵循此方法将允许您实现一些清理代码,这样您就不会遗留资源等等。
答案 2 :(得分:2)
您不能简单地停止服务器。关闭过程可能需要一段时间才能进行清理,因为您需要确保一致性。
想象一下数据库服务器,如果您只是在执行事务时将其关闭,则可能会使其数据不一致。这就是关闭服务器通常需要一段时间的原因。
根据我的理解,关闭与服务器端客户端的连接应该会导致客户端侧面获得EOF。
<强> [EDIT-1] 强>
我在这个问题上已经深入研究了一下,因为我有一段时间没有使用套接字,因为我发现这个问题很有意思。我认为,正如其他人已经明确指出的那样,唯一的选择是关闭套接字,根据Javadocs会自动关闭输入和输出流/
如果线程没有被IO阻塞,但处于等待状态或休眠状态,我认为仍然建议为给定套接字的相应工作线程发出Thread.interrupt();因为无法确定是否阻止了每个线程的状态。
public static class IOServerWorker implements Runnable{
private Socket socket;
public IOServerWorker(Socket socket){
this.socket = socket;
}
@Override
public void run() {
String line = null;
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while( (line = reader.readLine())!=null){
System.out.println(line);
}
reader.close();
}catch(IOException e){
//TODO: do cleanup here
//TODO: log | wrap | rethrow exception
}
}
}