2013-02-26 23 views
0

使用Countdownlatch和執行人沒有得到預期的輸出我很新到Java多線程。努力學習countdownlatch和執行者在Java線程和實施未來下列代碼 -而在Java

import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class ExecutorBasicFramework { 


    class MyThread extends Thread{ 

     int iCount ; String name; 
     CountDownLatch latch; 

     public MyThread(int iCount, String name, CountDownLatch latch) { 
      super(); 
      this.iCount = iCount; 
      this.name = name; 
      this.latch = latch;   
     } 

     @Override 
     public void run() { 
      for(int i=0;i<10;i++){ 
       System.out.println(name+" Printing .... "+ ++iCount+" L "+latch.getCount()); 
       try { 
        Thread.sleep(100); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       }    
      } 
      latch.countDown(); 

     } 

    } 

    public ExecutorBasicFramework() { 
     createThread(); 
    } 


    private void createThread() { 
     ExecutorService exec = Executors.newFixedThreadPool(10); 
     CountDownLatch latch = new CountDownLatch(10); 
     for(int i=0;i<10;i++){   
      MyThread thread = new MyThread(i*10, ""+i,latch); 
      exec.execute(thread); 

      try { 
       latch.await(); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 

     exec.shutdownNow();  

    } 

    public static void main(String[] args) { 
     new ExecutorBasicFramework(); 
    } 

} 

輸出結果 -

0 Printing .... 1 L 10 
0 Printing .... 2 L 10 
0 Printing .... 3 L 10 
0 Printing .... 4 L 10 
0 Printing .... 5 L 10 
0 Printing .... 6 L 10 
0 Printing .... 7 L 10 
0 Printing .... 8 L 10 
0 Printing .... 9 L 10 
0 Printing .... 10 L 10 

,然後流程就像是一直等下去。 我的預期輸出如上所示,但在打印0之後,它應該輸出1至9的相似輸出,然後程序應該停止。

我覺得countdownlatch在等待,等待其不會增加執行的下一個櫃檯。所以我無法獲得預期的產出。 我期待輸出如下 -

0 Printing .... 1 L 10 
0 Printing .... 2 L 10 
0 Printing .... 3 L 10 
0 Printing .... 4 L 10 
0 Printing .... 5 L 10 
0 Printing .... 6 L 10 
0 Printing .... 7 L 10 
0 Printing .... 8 L 10 
0 Printing .... 9 L 10 
0 Printing .... 10 L 10 


1 Printing .... 11 L 9 
1 Printing .... 12 L 9 
1 Printing .... 13 L 9 
1 Printing .... 14 L 9 
1 Printing .... 15 L 9 
1 Printing .... 16 L 9 
1 Printing .... 17 L 9 
1 Printing .... 18 L 9 
1 Printing .... 19 L 9 
1 Printing .... 20 L 9 

and So on ... 
2 Printing .... 21 L 8 
2 Printing .... 22 L 8 
2 Printing .... 23 L 8 

與鎖的每個遞減計數器,下一個線程池是必須 執行計數至10,然後再次它必須減少鎖 計數器,並再次過程重複,直到線程9完成 相同

請建議一些輸入。

+0

您是否試圖等待所有工作完成?這裏的目標是什麼? – Gray 2013-02-26 17:46:36

回答

1

如果您的目的是使用CountDownLatch直到所有線程都執行有main()方法等待,那麼你應該移動latch.await()用於提交線程循環。 另外,如果不再次設置中斷標誌,則不應該吃InterruptedException。 (see this article)。

修正應該是這樣的:

for(int i=0;i<10;i++){   
    MyThread thread = new MyThread(i*10, ""+i,latch); 
    exec.execute(thread); 
} 
try { 
    latch.await(); 
} catch (InterruptedException e) { 
    Thread.currentThread().interrupt(); 
} 

雖然這肯定會工作,鎖存器是最理想的方式使用ExecutorService時等待一個Runnable的另一個線程,執行。如果您使用submit()而不是​​,則可以使用submit()返回的Future通過調用get()來等待提交的Runnable的完成。

3

所以要配置的10 new CountDownLatch(10)一個倒計時值,但你的代碼是唯一的每個線程遞減一次。你叉僅有1線後,你再等待鎖,但它正坐在9

MyThread thread = new MyThread(i*10, ""+i,latch); 
exec.execute(thread); 
latch.await(); 

不知道你的意圖是什麼,但也許latch.countDown();應該的在線程循環?

for(int i=0;i<10;i++) { 
    ... 
    // if you want the latch to count-down 10 times, it should be inside the loop 
    latch.countDown(); 
} 
// it should not go here, outside the loop 

如果目標是要等待所有作業完成,你可以做到這一點與ExecutorService.awaitTermination(...)方法:

// submit jobs in loop 
exec.shutdown(); 
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); 

此外,你應該在你MyThread延長Thread類。您應該執行Runnable。爲什麼你的代碼工作的唯一原因是,Thread也實現RunnableMyThread應該ThreadExecutorService需要RunnableCallable,而不是Thread。它在內部管理服務的線程。

+0

我已經更新了我的預期輸出,並感謝關於可運行的建議。 – 2013-02-26 17:45:05

+1

@格雷肯定在這裏說過這一百萬次:) – 2013-02-26 17:51:35

+0

不行@RalfH。 100k上衣! ;-) – Gray 2013-02-26 17:52:09

0

感謝所有的投入。 我發現了一個更簡單的解決方案來獲得我的預期。 我剛剛使用了Executors.newSingleThreadExecutor();,因爲它已確保所有任務都能保證按順序執行。