2012-08-31 32 views
0

我有1個線程誰唯一的工作就是抓住DatagramPackets關閉套接字,並在緩衝區中把它們粘。另一個線程處理該緩衝區,處理DatagramPackets。我想有一個線程池在這個緩衝區中工作。Java的線程池多個相同任務

我曾想過使用一個固定的線程池來做到這一點。爲此,我是否需要創建池,然後提交足夠的可運行子進行執行以填充它?我曾希望有一種方式來說「這是我希望你執行的線程/可運行,這是我想要運行多少,GO!」。有這樣的方法嗎?除了固定線程池之外的東西更適合嗎?

回答

1

當您使用ExecutorService時,您將Runnable作業提交給由池中的線程依次運行的線程池。你可以做下列之一:

  1. 讓每個Runnable坐在一個循環,在循環來處理每一個數據包從一個BlockingQueue出隊。這可能比它們全部在緩衝區對象周圍同步更容易。喜歡的東西:

    public void run() { 
        while (!shutdown) { 
         packet = packetQueue.take(); 
         processPacket(packet); 
        } 
    } 
    
  2. 或者,可以將每個數據包提交到線程池的工作本身雖然可能會增加你的目標負載。您可以處理每個數據包,提取有效負載,並使用處理負載的run()方法在負載周圍創建Runnable包裝。在Runnable類的內容會是這樣的:

    Payload payload; 
    public void run() { 
        // process packet here 
        processPayload(payload); 
    } 
    

使用這兩種機制,我會選擇最適合自己的處理器的數量和處理任務的性質相匹配的固定線程號。下面的例子使用了處理器的數量,但您可能想要關閉一些GC或其他任務。如果其他IO上的處理塊可能需要更多。只有性能測試纔會告訴你最佳值是什麼。

// start a pool that uses the number of threads that there are processors 
ExecutorService threadPool = Executors.newFixedThreadPool(
    Runtime.getRuntime().availableProcessors()); 
+0

#1似乎違背了線程池的精神 - 將工作單元調度到最多N個線程池。相反,您要旋轉所有N個線程(其中N =最大池大小),並且每個線程都在隊列中等待並等待隊列,直到工作進入。如果這樣做,您可以直接創建N個線程並跳過線程池完全。 – JimN

+1

還有一件事 - 按照書面的說法,#1的關閉策略並不完全正常,因爲線程可能會永遠在包隊列中等待,並且從不重新檢查「關閉」並終止。在這種情況下,我通常使用「毒丸」方法來表示線程應該終止。 – JimN

+1

真的任何需要線程的任務都會通過線程池@Jim得到改進。即使在#1的情況下。 – Gray

1

Executors.newFixedThreadPool創建工作得很好的固定線程池。

實施的內部語義是這樣的線程池,將優先考慮創建一個新的線程,直到達到其首選大小(核心池大小),這似乎是你想要的。