2012-04-05 50 views
1

我目前正在編寫多個客戶端將連接到的服務器。通信協議基本上是服務器向客戶端發送任務,客戶端在任務執行時響應。客戶端保持連接到服務器,不應斷開連接。使用執行器代替服務器套接字客戶端的新線程

目前我開始一個新的線程來處理每個客戶端。在精神我目前的解決方案是這樣的:(來源從Java Concurrency in practice

public class ThreadPerTaskWebServer { 
    public static void main(String[] args) throws IOException { 
     ServerSocket socket = new ServerSocket(80); 
     while (true) { 
      final Socket connection = socket.accept(); 
      Runnable task = new Runnable() { 
       public void run() { 
        handleRequest(connection); 
       } 
      }; 
      new Thread(task).start(); 
     } 
    } 

    private static void handleRequest(Socket connection) { 
     // request-handling logic here 
    } 
} 

但我想用執行人,因爲他們似乎更穩定,更好的擴展。因此,爲了讓服務器能夠向客戶端發送消息,我需要跟蹤運行它們的Executor的客戶端。所以,如果我在什麼地方客戶的的CopyOnWriteArrayList客戶端,然後在服務器類是這樣的:

Socket clientSocket = serverSocket.accept(); 
// The runnable that takes care of a client 
ClientHandler c = new ClientHandler(clientSocket, this); 
// Start executing the ClientHandler 
exec.execute(c); 
// Add clients to CopyOnWriteArrayList 
clients.add(c); 

這將讓我來遍歷的CopyOnWriteArrayList,以便將命令發送到所有客戶端,並且還刪除不連接的。這是一個強大的解決方案嗎?如果可執行文件由於某種原因會向其傳播異常,那麼Executor會發生什麼情況?

+0

您在混合客戶端和服務器。在你的情況下,客戶端是服務器,反之亦然。 – ahanin 2012-04-05 19:21:37

+1

@ahanin我同意這不是完全清楚,但我認爲這是*最*正確的描述。由於客戶端連接到服務器(它具有ServerSocket),因此它變成了每個定義的服務器:) – Teletha 2012-04-05 19:38:28

+0

我沒有困惑,我完全理解了什麼是意圖,我只是想指出@Teletha正在混淆概念。在所描述的情況下,客戶端是一種提供「服務器」請求來執行任務的工作者代理。 – ahanin 2012-04-05 19:52:01

回答

1

這是一個健壯的解決方案嗎?

是的,我認爲是。您需要確保在固定大小的池中分配適當數量的線程或使用動態池。

如果可執行文件由於某種原因會向其傳播異常,那麼Executor會發生什麼情況?

如果你的代碼拋出一個RuntimeException,則執行池中的線程執行的代碼將停止,但池中的線程數將會減少,並創建如果該服務已不是關機另一個線程。所以線程池將繼續正常運行。

這將讓我來遍歷的CopyOnWriteArrayList,以便將命令發送到所有客戶端,並且還刪除斷開連接的那些

你不會需要刪除斷開連接的那些,除非你保存的參考給他們當然。否則我不能評論這個要求。

1

如果您選擇每個連接的線程方式,並且您不想使用NIO api,我相信這是一個很好的解決方案。但請記住,如果您的池大小小於併發請求數,那麼您的客戶端將處於等待狀態,直到前一個請求結束。

關於如果在任務中遇到異常會發生什麼情況:線程終止,但執行程序將創建其他線程。