CyclicBarrier與CountDownLatch、柵欄與計數器

    在多線程設計中,我猜常常會遇到線程間相互等待以及某個線程等待1個或多個線程的場景,比如多線程精密計算和大量數據處理,這裏寫下我自己的體會和理解。

   

    我想應該有很多辦法,如果是簡單的1:1關係,那麼可以wait()和notify()解決,就像一把鎖和一把鑰匙;如果是1:N關係,這個1就需要關心N的所有狀態了,最笨的辦法是1可以去查看N當前的狀態,輪詢詢問工作是否做完。而好點的辦法是N做完後主動告訴1,然後N就會有2種選擇,要麼聽從1的命令,要麼繼續幹自己其他的活。

 

    用傳統的方法我想應該是都能實現的,而JDK1.5提供了CyclicBarrier與CountDownLatch來解決了這兩個問題,而她們的區別是:

    CyclicBarrier使所有線程相互等待,而CountDownLatch使一個或多個線程等待其他線程。區別類似上面藍色字體,CountDownLatch不會等待其他線程了,只要做完自己的工作就幹自己的活去了,也就是run()方法裏其他的任務。

 

Example:

public static void testCountDownLatch() throws InterruptedException{
  CountDownLatch cdl=new CountDownLatch(2);
  ExecutorService exe=Executors.newFixedThreadPool(2);
   class Bow implements  Runnable{
    CountDownLatch cdl;
    public Bow(CountDownLatch cdl){
    this.cdl=cdl; 
    }
    public void run(){
     System.out.println("The bow is coming");
     System.out.println("kick a bow ");
     this.cdl.countDown();
     System.out.println("do other thing");
     }
   }
  exe.execute(new Bow(cdl));
  exe.execute(new Bow(cdl));
  exe.shutdown();
  System.out.println("Wait...");
    cdl.await();
    System.out.println("End..");
 
 }

	public static void main(String[] args) {
		try {
			Test.testCountDownLatch();
		} catch (InterruptedException e) {
		}
	}

 

輸出的結果爲:

 

The bow is coming
kick a bow
do other thing
Wait...
The bow is coming
kick a bow
do other thing
End..

 

如上所說do other thing不受影響。

 

寫了一個CyclicBarrier的例子:

public static void testCyclicBarrier() throws InterruptedException, BrokenBarrierException{
	    CyclicBarrier barr=new CyclicBarrier(2+1);
		
		ExecutorService exe=Executors.newFixedThreadPool(2);
		 class Bow implements  Runnable{
			 CyclicBarrier barr;
				public Bow(CyclicBarrier barr){
				this.barr=barr;	
				}
				public void run(){
					System.out.println("The bow is coming");
					System.out.println("kick a down");
					try {
						barr.await();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (BrokenBarrierException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println("do other thing");
					}
			}
		exe.execute(new Bow(barr));
		exe.execute(new Bow(barr));
		exe.shutdown();
		System.out.println("Wait...");
		barr.await();
	   System.out.println("End..");
	
	}


	public static void main(String[] args) {
		try {
			Test.testCyclicBarrier();
		} catch (InterruptedException e) {
		}
		catch (BrokenBarrierException e) {
		}
	}

 

輸出結果爲:

 

Wait...
The bow is coming
kick a down
The bow is coming
kick a down
do other thing
End..
do other thing

 

總結:

我們看到do other thing被阻塞了,直到最後才執行,可見,柵欄和計數器的目完全不同了。向Doug Lea牛人學習:)

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章