2017-02-14 67 views
1

我有下面的代碼片段:ExecutorService(int n)和Thread.activeCount()如何工作?

int k = 4; 

     ExecutorService e = Executors.newFixedThreadPool(k); 
     for (int i = 1; i <= k; i++) { 
      e.execute(new C(i)); 
      e.execute(new C(i)); 
     } 
     int active = Thread.activeCount(); 
     System.out.println(active); 
     e.shutdown(); 

清晰可見我提交兩份C每次迭代通過循環。在我的情況下,提交了8 C,即使ExecutorService的固定大小爲4. 也可以通過對活動線程數爲5進行計數來確認。

此行爲是否適用?我不明白爲什麼看起來只有4個新線程開始計算,儘管8個提交。如果有人能爲我清理ExecutorService和Thread.activeCount()的概念,我會非常高興。

+0

*是此行爲意*哪些行爲?你覺得什麼令人驚訝?你會期待什麼樣的行爲? – shmosel

+0

@shmosel,如果你不熟悉優惠條款,我會參考你的閱讀:http://dictionary.cambridge.org/dictionary/english/concessive-clause – blauerschluessel

+1

**在我的情況下,提交8 C,即使ExecutorService具有4 **的固定大小,Executors.newFixedThreadPool(int),處理當前同時運行的4個線程,並且當任何線程完成其執行時,通過e.execute(Runnable)排隊的其他4個線程將採用取代死亡線程的位置,否則那些OTHER 4 FROM 8線程將等待OTHER 8 FROM線程完成,這些線程在池中處於運行狀態,沒有意圖讓人驚訝,儘管 – ShayHaned

回答

3

您創建的ExecutorService的主要目標是固定大小的線程池(在您的情況下是四個線程)。如果您只看到爲您的八件作品創建的四個Thread實例,則它按照設計工作。

你似乎認爲應該有8個線程創建。想象一下,如果你提交了一百萬件作品,如果創建了一百萬個線程,那將是一場災難。

抽象允許您控制一次使用多少個線程,而不考慮要處理多少個項目。 ExecutorService處理重複使用四個線程的複雜性,根據需要處理所有傳遞給execute的項目。

一個可能解釋這個問題的類比是銀行。您創建了一個有四個出納員(線程池中的四個線程)和八個客戶(八個呼叫execute)的銀行。當出納員與客戶結束時,排隊的下一位客戶得到該出納員的服務。您可以通過致電execute將某人添加到隊列中,並由ExecutorService管理其他任何事情。您可以通過初始化ExecutorService(您可以創建許多不同的風格)來控制線程數量(出納員)。

+0

很好的回答!我從閱讀評論中得到了一個猜測,但現在證實了我的猜測。不過,我現在發現其他一些有趣的地方:例如:客戶究竟在哪裏?在你的比喻中,他們當然是在銀行,但是電話在哪裏?他們如何存儲,他們如何被訪問?是否也可以在中途操縱它們,也許爲什麼其他呼叫到達?你認爲我應該打開另一個問題嗎? – blauerschluessel

1

我不明白爲什麼看起來只有4個新的線程開始和計數,儘管8提交。

不要在線程和任務之間混淆。您已爲4個線程創建了固定的ThreadPool,並且池中只剩下4個線程。

檢查的Executors

/** 
    * Creates a thread pool that reuses a fixed number of threads 
    * operating off a shared unbounded queue. At any point, at most 
    * <tt>nThreads</tt> threads will be active processing tasks. 
    * If additional tasks are submitted when all threads are active, 
    * they will wait in the queue until a thread is available. 
    * If any thread terminates due to a failure during execution 
    * prior to shutdown, a new one will take its place if needed to 
    * execute subsequent tasks. The threads in the pool will exist 
    * until it is explicitly {@link ExecutorService#shutdown shutdown}. 
    * 
    * @param nThreads the number of threads in the pool 
    * @return the newly created thread pool 
    * @throws IllegalArgumentException if <tt>nThreads &lt;= 0</tt> 
    */ 
    public static ExecutorService newFixedThreadPool(int nThreads) { 
     return new ThreadPoolExecutor(nThreads, nThreads, 
             0L, TimeUnit.MILLISECONDS, 
             new LinkedBlockingQueue<Runnable>()); 
    } 

實現您可以找到有關官方文檔頁面的ThreadPoolExecutor各個參數的更多細節。

在你的情況下,線程數是4,職工任務(正在實施Runnable接口)數量8

他們是如何存儲,如何對它們進行訪問?是否也可以在中途操縱它們,也許爲什麼其他呼叫到達?

  1. 任務被提交到任務隊列(BlockingQueue
  2. 如果BlockingQueue滿(有界隊列),拒絕策略會被觸發。
  3. 如果BlockingQueue未滿,工作任務將等待線程提取它們。

相關SE帖子:

How to properly use Java Executor?

Task getting rejected although threads are available