CyclicBarrier 線程同步器

CountDownLatch,Semaphore,CyclicBarrier 都是在 JUC 下包含了一些常用的同步工具類,其實將其放在一起介紹印象會更加深刻,由於對其瞭解使用的先後順序,造成並沒有一起來介紹。

CountDownLatch:
當一個線程調用await方法時,就會阻塞當前線程。每當有線程調用一次 countDown 方法時,計數就會減 1。當 count 的值等於 0 的時候,被阻塞的線程纔會繼續運行。
CountDownLatch 的同步使用方法

Semaphore:
Semaphore 信號量,用來控制同一時間,資源可被訪問的線程數量,一般可用於流量的控制。
Semaphore 控制線程併發量

CyclicBarrier:
CyclicBarrier 是多個線程互相等待,一直到指定線程數到達指定位置。
1、CyclicBarrier 有兩個構造函數,

/**
     * Creates a new {@code CyclicBarrier} that will trip when the
     * given number of parties (threads) are waiting upon it, and which
     * will execute the given barrier action when the barrier is tripped,
     * performed by the last thread entering the barrier.
     *
     * @param parties the number of threads that must invoke {@link #await}
     *        before the barrier is tripped
     * @param barrierAction the command to execute when the barrier is
     *        tripped, or {@code null} if there is no action
     * @throws IllegalArgumentException if {@code parties} is less than 1
     */
    public CyclicBarrier(int parties, Runnable barrierAction) {
        if (parties <= 0) throw new IllegalArgumentException();
        this.parties = parties;
        this.count = parties;
        this.barrierCommand = barrierAction;
    }

 /**
     * Creates a new {@code CyclicBarrier} that will trip when the
     * given number of parties (threads) are waiting upon it, and
     * does not perform a predefined action when the barrier is tripped.
     *
     * @param parties the number of threads that must invoke {@link #await}
     *        before the barrier is tripped
     * @throws IllegalArgumentException if {@code parties} is less than 1
     */
    public CyclicBarrier(int parties) {
        this(parties, null);
    }

根據源碼上面註釋,public CyclicBarrier(int parties) 當指定線程數到達等待的地方,所有線程往下走。 public CyclicBarrier(int parties, Runnable barrierAction) 這個方法當指定線程數到達等待的地方 ,先執行構造函數裏面的Runnable 的run方法,所有線程再繼續往下走。

1、public CyclicBarrier(int parties) 構造函數

public class CyclicBarrierTest {

    public static void main(String[] args) throws InterruptedException {
        CyclicBarrier barrier = new CyclicBarrier(3);
        SynchronizeRunner runner1 = new SynchronizeRunner("barrierq1", barrier);
        SynchronizeRunner runner2 = new SynchronizeRunner("barrierq2", barrier);
        SynchronizeRunner runner3 = new SynchronizeRunner("barrierq3", barrier);
        new Thread(runner1).start();
        new Thread(runner2).start();
        new Thread(runner3).start();

        Thread.currentThread().join(1000);
    }

}

    class SynchronizeRunner implements Runnable{

        private String name;
        private CyclicBarrier cyclicBarrier;

        public SynchronizeRunner(String name, CyclicBarrier cyclicBarrier) {
            this.name = name;
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            try {
                System.out.println(name+":開始進入run方法");
                cyclicBarrier.await();
                System.out.println(name+":跳過await方法");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

執行結果:

barrierq3:開始進入run方法
barrierq1:開始進入run方法
barrierq2:開始進入run方法
barrierq2:跳過await方法
barrierq1:跳過await方法
barrierq3:跳過await方法

2、 public CyclicBarrier(int parties, Runnable barrierAction) 構造函數

public class CyclicBarrierTest {


    public static void main(String[] args) throws InterruptedException {
        CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("CyclicBarrier 構造器中的run 休眠之前");
                    TimeUnit.SECONDS.sleep(2);
                    System.out.println("CyclicBarrier 構造器中的run 休眠之後");

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        SynchronizeRunner runner1 = new SynchronizeRunner("barrierq1", barrier);
        SynchronizeRunner2 runner2 = new SynchronizeRunner2("barrierq2", barrier);
        SynchronizeRunner runner3 = new SynchronizeRunner("barrierq3", barrier);
        new Thread(runner1).start();
        new Thread(runner2).start();
        new Thread(runner3).start();

        Thread.currentThread().join(1000);
    }
}

    class SynchronizeRunner implements Runnable{

        private String name;
        private CyclicBarrier cyclicBarrier;

        public SynchronizeRunner(String name, CyclicBarrier cyclicBarrier) {
            this.name = name;
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            try {
                System.out.println(name+":開始進入run方法");
                cyclicBarrier.await();
                System.out.println(name+":跳過await方法");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

class SynchronizeRunner2 implements Runnable {

    private String name;
    private CyclicBarrier cyclicBarrier;

    public SynchronizeRunner2(String name, CyclicBarrier cyclicBarrier) {
        this.name = name;
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        try {
            System.out.println(name + ":開始進入SynchronizeRunner2類中的run方法");
            cyclicBarrier.await();
            System.out.println(name + ":跳過開始進入SynchronizeRunner2類中的await方法");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }

}

執行結果:

barrierq3:開始進入run方法
barrierq1:開始進入run方法
barrierq2:開始進入SynchronizeRunner2類中的run方法
CyclicBarrier 構造器中的run 休眠之前
CyclicBarrier 構造器中的run 休眠之後
barrierq3:跳過await方法
barrierq2:跳過開始進入SynchronizeRunner2類中的await方法
barrierq1:跳過await方法

由2結果可知,await不一定必須是同一個類,只要指定線程到達對應地方就可以了。

如果看了可能會發現CyclicBarrier 和 CountDownLatch 非常相似,CyclicBarrier 是多個線程相互等待。CountDownLatch 是一個線程等待多個線程。

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