2015-12-14 113 views
2

我想在countDownLatch.getCount()爲零時關閉服務器,但不是關閉,而是等待接受套接字連接。這是處理傳入TCP請求的服務器代碼。無法關閉線程池

public static void start(File configFile, ReplyListener replyListener, CountDownLatch countDownLatch) { 
      try { 
       Server.init(configFile); 
       while (countDownLatch.getCount() != 0) { 
        //try { 
         Server.socket = serverSocket.accept(); 
         Message message = new Message(); 
         message.setSocket(Server.socket); 
         Server.pool.submit(new ServerTaskCallable(message.receive()).setReplyListener(replyListener)); 
        /*} catch (SocketTimeoutException e){ 
         System.out.println("Finished testing"); 
        }*/ 
       } 
       Server.socket.close(); 
       serverSocket.close(); 
       Server.pool.shutdownNow(); 
      } catch (IOException e) { 
       logger.error("Cannot start a server. The server thread will be terminated. Exception: ", e); 
       System.exit(0); 
      } 
     } 

這裏是線程達姆:

"[email protected]" prio=5 tid=0xe nid=NA runnable 
    java.lang.Thread.State: RUNNABLE 
     at java.net.PlainSocketImpl.socketAccept(PlainSocketImpl.java:-1) 
     at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:404) 
     at java.net.ServerSocket.implAccept(ServerSocket.java:545) 
     at java.net.ServerSocket.accept(ServerSocket.java:513) 
     at model.server.Server.start(Server.java:42) 
     at model.MainTest.lambda$main$3(MainTest.java:30) 
     at model.MainTest$$Lambda$2.2012232625.run(Unknown Source:-1) 
     at java.lang.Thread.run(Thread.java:745) 
     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
     at java.lang.Thread.run(Thread.java:745) 

"[email protected]" prio=5 tid=0x12 nid=NA waiting 
    java.lang.Thread.State: WAITING 
     at sun.misc.Unsafe.park(Unsafe.java:-1) 
     at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 
     at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) 
     at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442) 
     at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
     at java.lang.Thread.run(Thread.java:745) 

我怎樣才能正確地終止服務器線程池?

+0

你有沒有在'ServerSocket' [設置超時(https://docs.oracle.com/javase/8/docs/api/java/net/ServerSocket.html#setSoTimeout-int-) ? –

+0

它有助於終止一個線程池,但我想避免使用timeOut()(如果它當然可行)。 –

+0

我只能想到兩個選項第一個是超時,如上所述,基本上迫使你的代碼通過循環每隔一段時間。第二個是中斷從某個主線程接受調用的線程。 – Pace

回答

1

你有兩個選擇:

  1. 通過ServerSocket#setSoTimeout(int)坐落在ServerSocket超時。這會導致accept()每次發生超時時都會拋出一個SocketTimeoutException。您將需要捕捉裏面你的循環異常,以確保您的服務器不斷偵聽連接:

    while(countDownLatch.getCount() != 0) { 
        try { 
         socket = serverSocket.accept(); 
        } catch(SocketTimeoutException e) { 
         //timeout occurred! 
        } 
    } 
    
  2. 關閉通過ServerSocket#close()ServerSocket從不同的線程。這將拋出一個SocketAcception,終止accept()呼叫。這個異常可能會被外部的這個循環輕鬆地退出「監聽連接」行爲。