2013-07-30 24 views
0

我在尋找ExecutorService,它可根據需要創建線程,達到預定義的限制並在保持活動時間後銷燬空閒線程。按需線程數有限的執行程序

下面的構造函數創建一個ThreadPoolExecutor固定線程數:

// taken from Executors.newFixedThreadPool() 
new ThreadPoolExecutor(nThreads, nThreads, 
            0L, TimeUnit.MILLISECONDS, 
            new LinkedBlockingQueue<Runnable>()); 

所以我試圖創建一個ExecutorService這樣:

// taken from Executors.newCachedThreadPool() 
new ThreadPoolExecutor(0, nThreads, 
    CACHED_POOL_SHUTDOWN_DELAY, TimeUnit.SECONDS, 
    new SynchronousQueue<Runnable>()); 

但它不工作不如預期,當nThreads正在使用中,Executor不排隊新任務,但拋出RejectedExecutionException。我知道我可以實現一個處理程序,但它並沒有幫助我。

如何創建前面所述的Executor

回答

1

我發現了一個方法上that post但這正是我所需要的。
@assylias我認出你的答案,並改變了隊列的實施。

現在我的代碼如下所示:

parallelExecutor = new ThreadPoolExecutor(nThreads, nThreads, 
    CACHED_POOL_SHUTDOWN_DELAY, TimeUnit.SECONDS, 
    new LinkedBlockingQueue<Runnable>()); 

parallelExecutor.allowCoreThreadTimeOut(true); // this is the magic 

它就像一個固定的線程池,但這些核心這就是被允許的時間了。

1

如果無法排隊新任務,則會創建新線程,除非您已達到最大核心池大小。在你的情況下,隊列一次只能包含一個任務,所以如果你足夠快地提交任務,你可以達到最大的池大小並得到異常。

它適用於CachedThreadPool,因爲最大核心池大小很大(Integer.MAX_VALUE)。

您需要使用不同的隊列,例如類似於固定線程池示例中的新的LinkedBlockingQueue

備註:檢查實施文檔可幫助您瞭解詳細信息。特別是,ThreadPoolExecutor類的execute方法有:

/* 
    * Proceed in 3 steps: 
    * 
    * 1. If fewer than corePoolSize threads are running, try to 
    * start a new thread with the given command as its first 
    * task. The call to addWorker atomically checks runState and 
    * workerCount, and so prevents false alarms that would add 
    * threads when it shouldn't, by returning false. 
    * 
    * 2. If a task can be successfully queued, then we still need 
    * to double-check whether we should have added a thread 
    * (because existing ones died since last checking) or that 
    * the pool shut down since entry into this method. So we 
    * recheck state and if necessary roll back the enqueuing if 
    * stopped, or start a new thread if there are none. 
    * 
    * 3. If we cannot queue task, then we try to add a new 
    * thread. If it fails, we know we are shut down or saturated 
    * and so reject the task. 
    */ 
+0

謝謝,你說得對。但可能會發生成千上萬的排隊隊列,我不想創建如此龐大的隊列。 – Stephan

+0

@Stephan您需要對無法運行的任務(使用最大池大小)進行操作並且無法入隊(隊列已滿)...您可以限制隊列的大小,但您將收到一旦它已滿,就會發生異常。 – assylias

+1

這是真的。我從隊列的構造函數中刪除了'capacity'參數,因此它被設置爲'Integer.MAX_VALUE'。 – Stephan