[英]How to unblock a thread blocked on ServerSocket.accept()?
我有一個服務器線程與此代碼:
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
中的Executor
框架使用interrupt
來取消正在運行的任務。 此外,“關閉”任務不必知道正在被殺死的任務的任何內部。
但是,對accept
的調用不會響應中斷, 除非它是從ServerSocketChannel
創建的。 使用ServerSocket
構造函數創建的服務器將忽略中斷,我還沒有找到重新配置它的方法。
如果您無法更改創建服務器的代碼,請安排另一個線程在服務器套接字上調用close
。 無論用於創建服務器套接字的方法如何,這也會在accept
阻塞的線程中引發異常。
使用SSL時,這是一個非常大的痛苦。 JSSE套接字不是從InterruptibleChannel
創建的,並且不會響應線程上的簡單中斷。
我只是注意到問題是在沒有通知客戶端的情況下無法關閉服務器。 成功中斷套接字會導致其關閉。
在accept
此調用的調用應該不是問題,因為如果服務器套接字在accept中被阻止,則客戶端未連接。 這應該只是Socket
實例的一個問題,它代表當前的連接。
如果這不滿足通知要求,則可能需要在非阻塞模式下使用NIO的ServerSocketChannel
進行返工。
您應該能夠從另一個線程關閉套接字。
中斷(這取決於中斷點以相同的方式取消取決於取消點)也不會關閉(接受不響應關閉其文件描述符)。 您必須與accept進行通信(嘗試sendto,並發出關閉通知)以通知它不繼續接受。 至少在linux上就是這種情況; 不知道在其他平台上是什么樣的。
我一直面臨着同樣的問題。 我的工作解決方案包括關閉ServerSocket對象(serverSocket.close()); 這樣做會導致accept()方法拋出SocketException,這是你想要做的。
文森特
你試過Thread.interrupt()嗎?
如果此線程在可中斷通道上的I / O操作中被阻塞,則通道將關閉,線程的中斷狀態將被設置,並且線程將收到ClosedByInterruptException。
如果此線程在Selector中被阻塞,則線程的中斷狀態將被設置,並且它將立即從選擇操作返回,可能具有非零值,就像調用選擇器的喚醒方法一樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.