2016-01-13 60 views
2

我創建了一個線程池,其中每個線程都從隊列中獲取對象並對其進行處理。我不確定我是否以正確的方式實施它。這裏的代碼:使用相同對象的線程池

public class HandlerThreadsPool<T> { 

private BlockingQueue<T> queue; 
private IQueueObjectHandler<T> objectHandler; 

private class ThreadClass implements Runnable { 

    @Override 
    public void run() { 
     while (true) { 
       objectHandler.handleItem(queue.take()); 
     } 
    } 
} 

public HandlerThreadsPool(int numberOfThreads, BlockingQueue<T> queue, IQueueObjectHandler<T> dataHandler){ 

     this.queue = queue; 
     this.objectHandler = dataHandler; 
     ExecutorService service = Executors.newFixedThreadPool(numberOfThreads); 
     for (int i = 0; i < numberOfThreads; i++) 
       service.execute(new ThreadClass()); 
     service.shutdown(); 
} 

} 

dataHandler處理對象做一些東西。這樣正確嗎? 謝謝

回答

0

首先,創建,提交和關閉ExecutorService內部構造函數不是一個好習慣。 看shutdown() javadoc

發起一個有序的關閉在以前已提交任務的執行中 ,但沒有新的任務將被接受。如果已關閉,則調用沒有 附加效果。

你沒有張貼IQueueObjectHandler,但它似乎對我來說,你的ThreadClass作業將無限運行,關閉當然,如果你沒有被明確地拋出內部objectHandler.handleItem(..)一些未經檢查的異常這將是錯誤的阻止他們。由於這些無限運行的守護進程線程,您可能會遇到JVM終止問題。 (JVM graceful termination conditions
此外,在執行queue.take()時,您不會捕獲InterruptedException,這會導致編譯時錯誤。正確處理InterruptedException將幫助您停止可能的shutdownNow()

所以

  • 不要關機池在構造函數中,這會導致問題。如果您不想在其他地方關機,請使用Runtime.getRuntime().addShutdownHook(..)
  • 使用shutdownNow()實際上阻止執行程序的線程,如果它們處於無限循環中,則爲ThreadClass內部的InterruptedException處理此操作。或者,您可以使用volatile booleanAtomicBoolean標誌來阻止它們,該標誌指示狀態,正在運行/已停止。檢查循環中的標誌,並在需要關閉作業時將其更改爲false
  • 使ExecutorService service成爲一個實例變量,不是本地的。鬆動參考運行ExecutorService看起來很糟糕。這可以幫助你在別的地方。