多執行緒學習(二)CountDownLunch與CyclicBarrier

liudashuang2017發表於2018-04-14

兩個看上去有點像的類,都在java.util.concurrent下,都可以用來表示程式碼執行到某個點上,二者的區別在於:

(1)CyclicBarrier的某個執行緒執行到某個點上之後,該執行緒即停止執行,直到所有的執行緒都到達了這個點,所有執行緒才重新執行;CountDownLatch則不是,某執行緒執行到某個點上之後,只是給某個數值-1而已,該執行緒繼續執行

(2)CyclicBarrier只能喚起一個任務,CountDownLatch可以喚起多個任務

(3)CyclicBarrier可重用,CountDownLatch不可重用,計數值為0該CountDownLatch就不可再用了

CyclicBarrier

public class CyclicBarrierTest {
    /**
     * 工作執行緒
     */
    private static class Work implements Runnable{
        private CyclicBarrier cyclicBarrier ;

        public Work(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }
        //只有所有人都完成第一階段才能開始第二階段
        public void run() {

            firstwork();
            try {
                //等待完成第一階段工作
                cyclicBarrier.await();
                secondWork();
                //完成第二階段工作
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
        //work1
        private void firstwork(){
            System.out.println(Thread.currentThread().getName()+"完成第一項工作");
        }
        //work2
        private void secondWork(){
            System.out.println(Thread.currentThread().getName()+"完成第二階段");
        }
    };

    //通知執行緒
    private static class NoticeThread implements Runnable{
        boolean [] flag = new boolean[2] ;
        public void run() {
            if (!flag[0]){
                System.out.println("通知:第一階段完成");
                flag[0] = true;
            }else
            if( !flag[1]){
                System.out.println("通知:第二階段完成");
            }
        }
    }
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(10,new NoticeThread());
        for (int i =0 ;i<10 ;i++){
            new Thread(new Work(cyclicBarrier)).start();
        }
    }
}

結果

Thread-0完成第一項工作
Thread-2完成第一項工作
Thread-1完成第一項工作
Thread-4完成第一項工作
Thread-3完成第一項工作
Thread-7完成第一項工作
Thread-8完成第一項工作
Thread-6完成第一項工作
Thread-5完成第一項工作
Thread-9完成第一項工作
通知:第一階段完成
Thread-9完成第二階段
Thread-0完成第二階段
Thread-2完成第二階段
Thread-1完成第二階段
Thread-4完成第二階段
Thread-3完成第二階段
Thread-7完成第二階段
Thread-8完成第二階段
Thread-6完成第二階段
Thread-5完成第二階段
通知:第二階段完成

從結果看到 cyclicBarrier 阻塞所有執行緒, 之後 都到達後 ,會喚醒一個通知執行緒, 之後所有阻塞的工作執行緒繼續執行, 都到達第二階段 之後喚醒 通知執行緒,再繼續. 並且一個 cyclicBarrier可以重複利用.

CountDownLunch

public class CountDownLunchTest {
    private CountDownLatch countDownLatch  = new CountDownLatch(5);

    public void doWork(){
        countDownLatch.countDown();
        System.out.println(countDownLatch.getCount());
    }

    public static void main(String[] args) throws InterruptedException {
        final CountDownLunchTest test = new CountDownLunchTest();
        Runnable runnable = new Runnable() {
            public void run() {
                test.doWork();
            }
        };
        for (int i = 0; i <5; i++) {
            new Thread(runnable).start();
        }
        test.countDownLatch.await();
        System.out.println("end");
    }
}

其他參考:https://github.com/wowdouble/wowdouble/tree/master/threaddemo

相關文章