[英]Terminating application and ScheduledExecutorService; Thread
我有以下邏輯(簡化):
public class Application {
public static volatile boolean stopServer;
private static ScheduledExecutorService taskScheduler;
private static Thread listenerThread;
public static synchronized void switchStopServer() {
stopServer = true;
listenerThread.interrupt();
taskScheduler.shutdownNow();
}
public static void main(String[] args) {
int threadPoolSize = 4;
taskScheduler = Executors.newScheduledThreadPool(threadPoolSize);
listenerThread = new ListenerThread();
taskScheduler.schedule(listenerThread, 0, TimeUnit.NANOSECONDS);
}
}
public class ListenerThread extends Thread {
private static ServerSocket serverSocket;
private Socket socketConnection;
@Override
public void run() {
while (!Application.stopServer) {
try {
socketConnection = serverSocket.accept();
new CommunicatorThread(socketConnection).start();
} catch (SocketException e) {
} catch (Exception e) {
}
}
}
private static void closeServerSocket() {
try {
if (serverSocket != null && !serverSocket.isClosed()) serverSocket.close();
} catch (Exception e) { }
}
@Override
public void interrupt() {
closeServerSocket();
super.interrupt();
}
}
我想要實現的是以正確的方式終止Thread
。 首先,這是( switchStopServer()
)正確的方法,還是有更好的解決方案?
我對ScheduledExecutorService
有點困惑,因為shutdownNow()
不會中斷Thread
s, ScheduledFuture.cancel(true)
也沒有(至少對我來說它沒有),所以我不能打斷ServerSocket.accept()
。 我知道,在我的例子中,不需要ScheduledExecutorService
,但在我的實際應用程序中有。
我相信你的問題是你在混淆Thread
和Runnable
。 即使ListenerThread
擴展了Thread
,它實際上也不是它自己的線程。 該線程由ExecutorService
線程池管理,該線程池只調用run()
方法。 這只是[有點]工作,因為Thread
也實現了Runnable
。 當你調用ListenerThread.interrupt()
你不是在打斷線程池中的線程,盡管你正在調用你的interrupt()
方法而只是直接在調用線程中。 這應該關閉套接字,因為它從外部調用closeServerSocket()
。
當您調用ScheduledFuture.cancel(true)
或shutdownNow()
,應該中斷池線程,但這不會調用您的interrupt()
方法。 您可以在run()
方法中使用Thread.currentThread().isInterrupted()
來測試中斷。
您應該從擴展Thread
更改ListenerThread
,而是讓它只實現Runnable
( 請參閱下面的編輯 )。 您將需要在run()
方法中執行類似以下循環的操作:
while (!Application.stopServer && !Thread.currentThread().isInterrupted()) {
要中斷accept()
方法,您將不得不從另一個線程關閉serverSocket
。 這很可能是由調用interrupt()
的線程完成的。 它應該關閉套接字, shutdownNow()
或cancel()
線程池,然后它可以等待池終止。
編輯:
實際上,我想知道你為什么要為ListenerThread
使用一個池,因為它只會有一個,它會被立即調度,它只是直接在任何連接上啟動一個新線程。 我會完全刪除你的taskScheduler
池,讓ListenerThread
繼續擴展Thread
,然后只調用new ListenerThread().start();
。
外部線程仍然只是關閉serverSocket
以停止ListenerThread
。 如果你還需要關閉所有連接,那么ListenerThread
需要保留socketConnection
的集合,這樣當accept()
拋出IOException
時它可以調用它們的close()
。
另外,目前你有private Socket socketConnection;
這是誤導性的,因為它會在每次調用accept()
后發生變化。 我把它重寫為:
Socket socketConnection = serverSocket.accept();
new CommunicatorThread(socketConnection).start();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.