我有一个带有这段代码的服务器线程:
public void run() {
try {
ServerSocket server;
EneaLog.printLog("Server is running.");
server = new ServerSocket(this.portnumber);
while (true) {
new EneaServerConnection(server.accept(), this.project,stopped).start();
if (stopped) {
EneaLog.printLog("Server safe-shutdown completed.");
EneaLog.printLog("Hi!");
server.close();
return;
}
}
} catch (IOException ex) {
Logger.getLogger(EneaServer.class.getName()).log(Level.SEVERE, null, ex);
project.getExceptionHandler().handler(ex);
}
}
和这样的关机方法:
public void shutdown() {
EneaLog.printLog("Server shutdown NOW!");
stopped = true;
}
我希望关闭可以解锁正在等待 server.accept() 的线程,否则我必须在服务器关闭之前等待连接。
我不能在 shutdown() 中执行 server.close() 因为我必须向注册客户端发出服务器即将关闭的信号。
有什么想法吗?
最佳答案
我尝试设计我的代码,使其可以通过中断“关闭”。主要是因为Java并发包中的Executor
框架使用了interrupt
来取消正在运行的任务。此外,“关闭”任务不必知道被终止任务的任何内部信息。
但是,调用accept
不会响应中断除非它是created from a ServerSocketChannel
.使用 ServerSocket
构造函数创建的服务器将忽略中断,我还没有找到重新配置它的方法。
如果您无法更改创建服务器的代码,请安排另一个线程在服务器套接字上调用close
。这也会在 accept
上阻塞的线程中引发异常,无论用于创建服务器套接字的方法如何。
事实证明,这在使用 SSL 时是一个非常大的痛苦。 JSSE 套接字不是从 InterruptibleChannel
创建的,也不会响应线程上的简单中断。
我刚刚注意到问题说服务器不能在不通知客户端的情况下关闭。成功中断套接字会导致其关闭。
在调用 accept
时这应该不是问题,因为如果服务器套接字在 accept 中被阻塞,则客户端不会连接。这应该只是代表当前连接的 Socket
实例的问题。
如果这不能满足通知要求,则可能需要在非阻塞模式下使用 NIO 的 ServerSocketChannel
进行返工。
关于java - 如何取消阻塞在 ServerSocket.accept() 上阻塞的线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1510403/