美文网首页java进阶干货程序员
CountDownLatch和CyclicBarrier用法及例

CountDownLatch和CyclicBarrier用法及例

作者: BK_凌霄 | 来源:发表于2017-10-17 14:42 被阅读0次

    CountDownLatch和CyclicBarrier用法及例子

    1.都是用来实现其他任务都完成后,然后再执行一个任务的需求,类似赛跑比赛,需要等所有运动员到达终点后,才能开始下一步颁奖。
    2.CountDownLatch是一次性的,不能重复使用;CyclicBarrier是可重复的;
    3.CountDownLatch使用时,在每个需要等待的地方调用await,在每个触发条件的地方调用countDown即可,countDown次数达到指定次数,会唤醒所有await;
    4.CyclicBarrier使用时,在每个需要等待的地方调用await,然后内部会自动统计await次数,到达指定次数后,自动回调,完成回调后,唤醒所有await。

    例子1,每个任务计算一个值,都完成计算后进行下一步计算。Test2模拟了普通的计算任务,都完成后,会从latch.await()那个地方继续执行:
    public class Main {
    private static final int N = 5;

    public static final void main(String[] args) {
        testCountDownLatch();
    }
    
    private static void testCountDownLatch() {
        CountDownLatch latch = new CountDownLatch(N);
        Test2[] tt = new Test2[N];
        for (int i = 0; i < N; i++) {
            tt[i] = new Test2(latch);
            new Thread(tt[i]).start();
        }
        System.out.println("Main is Wait.");
        try {
            latch.await();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        int total = 0;
        for (int i = 0; i < N; i++) {
            total += tt[i].ret;
        }
        System.out.println("Main is Wait Over!" + total);
    }
    

    }

    public class Test2 implements Runnable {
    private CountDownLatch latch;

    public Test2(CountDownLatch latch) {
        this.latch = latch;
    }
    
    public int ret = 0;
    
    @Override
    public void run() {
        System.out.println("Thread-" + Thread.currentThread().getName() + " is Running");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        ret = 1;
        System.out.println("Thread-" + Thread.currentThread().getName() + " is finish Task!");
        latch.countDown();
    
    }
    

    }

    输出结果:
    Thread-Thread-1 is Running
    Thread-Thread-2 is Running
    Thread-Thread-3 is Running
    Main is Wait.
    Thread-Thread-4 is Running
    Thread-Thread-0 is Running
    Thread-Thread-2 is finish Task!
    Thread-Thread-4 is finish Task!
    Thread-Thread-3 is finish Task!
    Thread-Thread-1 is finish Task!
    Thread-Thread-0 is finish Task!
    Main is Wait Over!5

    例子2,用CountDownLatch实现的一个运动员比赛的程序:
    public class Main {
    // 运动员数量
    private static final int N = 5;

    public static final void main(String[] args) {
        testCountDownLatch2();
    }
    
    private static void testCountDownLatch2() {
        // 运动员准备好的信号
        CountDownLatch latchStart = new CountDownLatch(N);
        // 运动员都完成比赛的信号
        CountDownLatch latchOver = new CountDownLatch(N);
        // 正式开始比赛的信号
        CountDownLatch startSignal = new CountDownLatch(1);
        for (int i = 0; i < N; i++) {
            new Thread(new Player(i, latchStart, latchOver, startSignal)).start();
        }
        System.out.println("等待运动员都准备好");
        try {
            // 等待运动员都准备好
            latchStart.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("开始比赛");
        // 开始比赛信号
        startSignal.countDown();
        try {
            // 等待所有运动员完成比赛
            latchOver.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("所有运动员都完成了比赛,比赛结束");
    }
    

    }

    public class Player implements Runnable {
    private CountDownLatch latchStart;
    private CountDownLatch latchOver;
    private CountDownLatch startSignal;

    private int id;
    
    private static Random sRandom = new Random();
    
    public Player(int id, CountDownLatch latchStart, CountDownLatch latchOver, CountDownLatch startSignal) {
        this.id = id;
        this.latchStart = latchStart;
        this.latchOver = latchOver;
        this.startSignal = startSignal;
    }
    
    @Override
    public void run() {
        // 模拟准备时间
        try {
            Thread.sleep(sRandom.nextInt(2000));
        } catch (InterruptedException e2) {
            e2.printStackTrace();
        }
        System.out.println("Player" + id + "准备好" + System.currentTimeMillis());
        // 运动员准备好
        this.latchStart.countDown();
        try {
            // 等待裁判说开始
            this.startSignal.await();
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        System.out.println("Player" + id + " 开始跑" + System.currentTimeMillis());
        long duration = sRandom.nextInt(5000);
        try {
            // 模拟跑的时间
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Player" + id + " 完成比赛,耗时:" + duration);
        // 运动员完成比赛
        this.latchOver.countDown();
    }
    

    }

    输出结果:
    等待运动员都准备好
    Player0准备好1508221461341
    Player2准备好1508221461832
    Player3准备好1508221462335
    Player4准备好1508221462369
    Player1准备好1508221463031
    开始比赛
    Player0 开始跑1508221463032
    Player4 开始跑1508221463032
    Player3 开始跑1508221463032
    Player2 开始跑1508221463032
    Player1 开始跑1508221463032
    Player1 完成比赛,耗时:1202
    Player2 完成比赛,耗时:1939
    Player0 完成比赛,耗时:1947
    Player4 完成比赛,耗时:2878
    Player3 完成比赛,耗时:3974
    所有运动员都完成了比赛,比赛结束

    例子3,用CyclicBarrier实现例子1:
    public class Main {
    private static final int N = 5;

    public static final void main(String[] args) {
        testCyclicBarrier();
    }
    
    private static void testCyclicBarrier() {
        Test3[] tt = new Test3[N];
        CyclicBarrier barrier = new CyclicBarrier(N, new Runnable() {
    
            @Override
            public void run() {
                // await达到指定次数,随机选一个线程来执行这个任务
                System.out.println("Barrier All Task Finished,CurrentThread=" + Thread.currentThread().getName());
                int total = 0;
                for (int i = 0; i < N; i++) {
                    total += tt[i].ret;
                }
                System.out.println("计算结果是:" + total);
            }
        });
        for (int i = 0; i < N; i++) {
            tt[i] = new Test3(barrier);
            new Thread(tt[i]).start();
        }
    }
    

    }

    public class Test3 implements Runnable {
    private CyclicBarrier barrier;

    public Test3(CyclicBarrier barrier) {
        this.barrier = barrier;
    }
    
    public int ret = 0;
    
    @Override
    public void run() {
        System.out.println("Thread-" + Thread.currentThread().getName() + " is Running");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        ret = 1;
        System.out.println("Thread-" + Thread.currentThread().getName() + " is finish Task!");
        try {
            this.barrier.await();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Thread-" + Thread.currentThread().getName() + " exit!");
    
    }
    

    }

    输出结果:
    Thread-Thread-1 is Running
    Thread-Thread-0 is Running
    Thread-Thread-3 is Running
    Thread-Thread-4 is Running
    Thread-Thread-2 is Running
    Thread-Thread-3 is finish Task!
    Thread-Thread-2 is finish Task!
    Thread-Thread-1 is finish Task!
    Thread-Thread-0 is finish Task!
    Thread-Thread-4 is finish Task!
    Barrier All Task Finished,CurrentThread=Thread-4
    计算结果是:5
    Thread-Thread-4 exit!
    Thread-Thread-3 exit!
    Thread-Thread-0 exit!
    Thread-Thread-1 exit!
    Thread-Thread-2 exit!

    例子4,用CyclicBarrier实现例子2:
    public class Main {
    private static final int N = 5;

    public static final void main(String[] args) {
        testCyclicBarrier2();
    }
    
    private static void testCyclicBarrier2() {
        CyclicBarrier barrierPrepare = new CyclicBarrier(N, new Runnable() {
    
            @Override
            public void run() {
                // 准备完成
                System.out.println("所有运动员准备完毕,开始比赛");
                
            }
        });
        CyclicBarrier barrierOver = new CyclicBarrier(N, new Runnable() {
    
            @Override
            public void run() {
                // 比赛完成
                System.out.println("所有运动员比赛都完成了,结束比赛");
            }
        });
        for (int i = 0; i < N; i++) {
            new Thread(new Player2(i, barrierPrepare, barrierOver)).start();
        }
    }
    

    }

    public class Player2 implements Runnable {
    private CyclicBarrier barrierPrepared;
    private CyclicBarrier barrierOver;
    private int id;
    private static Random sRandom = new Random();

    public Player2(int id, CyclicBarrier barrierPrepared, CyclicBarrier barrierOver) {
        this.barrierPrepared = barrierPrepared;
        this.barrierOver = barrierOver;
        this.id = id;
    }
    
    public void run() {
        try {
            // 模拟准备比赛
            Thread.sleep(sRandom.nextInt(3000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("运动员" + id + "准备比赛");
        try {
            // 等待开始
            barrierPrepared.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        System.out.println("运动员" + id + "开始比赛" + System.currentTimeMillis());
        int duration = sRandom.nextInt(5000);
        try {
            // 模拟比赛耗时
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("运动员" + id + "完成比赛,比赛时长:" + duration);
        try {
            // 等待比赛结束
            barrierOver.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    
    }
    

    }

    输出结果:
    运动员2准备比赛
    运动员0准备比赛
    运动员1准备比赛
    运动员4准备比赛
    运动员3准备比赛
    所有运动员准备完毕,开始比赛
    运动员3开始比赛1508222334484
    运动员2开始比赛1508222334484
    运动员1开始比赛1508222334484
    运动员0开始比赛1508222334484
    运动员4开始比赛1508222334484
    运动员4完成比赛,比赛时长:777
    运动员0完成比赛,比赛时长:2640
    运动员1完成比赛,比赛时长:2952
    运动员3完成比赛,比赛时长:3843
    运动员2完成比赛,比赛时长:3924
    所有运动员比赛都完成了,结束比赛

    相关文章

      网友评论

        本文标题:CountDownLatch和CyclicBarrier用法及例

        本文链接:https://www.haomeiwen.com/subject/nwjduxtx.html