在多線程設計中,我猜常常會遇到線程間相互等待以及某個線程等待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牛人學習:)