并发-CountDownLatch 和 CyclicBarrier

Concurrent.util工具之CountDownLatch & CyclicBarrier

CountDownLatch用法:

经常用于监控一些初始化操作,等初始化都完毕之后,通知主线程进行继续操作!!   

CyclicBarrier

常用于多个线程都完成一定的准备工作之后,一起去执行操作。
例如: 你今天过生日,约定好,家人都到齐了,才能吃蛋糕,有一个人没到家,这个执行吃蛋糕的步骤就不能进行。

区别

这里写图片描述
CountDownLatch实例:

public class StudyConcurrentUtils {

    public static void main(String[] args) {
        /**
         * 源码解释的非常清楚:只有countDown被调用2次,await方法才能通过
         *
         * the number of times {@link #countDown} must be invoked
         *        before threads can pass through {@link #await}
         */
        final CountDownLatch countDownLatch = new CountDownLatch(2);

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    System.out.println("进入线程1...等待其他线程");
                    //线程阻塞
                    countDownLatch.await();
                    System.out.println("线程1继续开始执行其他工作");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程-1");


        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    System.out.println("进入线程2...");
                    //模拟实际工作,休眠3秒
                    Thread.sleep(3000);
                    System.out.println("线程2任务完成...countDown一次通知线程1");
                    countDownLatch.countDown();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程-2");



        Thread thread3 = new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    System.out.println("进入线程3...");
                    //模拟实际工作,休眠3秒
                    Thread.sleep(3000);
                    System.out.println("线程3任务完成...countDown一次通知线程1");
                    countDownLatch.countDown();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"线程-3");

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

这里写图片描述

CyclicBarrier事例:


/**
 * @author zhanghuilong
 * @version V1.0
 * @desc
 * @since 2018/01/11
 */
public class StudyConcurrentUtils1 {
    //内部类
    static class MyTask implements Runnable{
        private CyclicBarrier cyclicBarrier;
        private String taskNme;

        public MyTask(CyclicBarrier cyclicBarrier, String taskNme) {
            this.cyclicBarrier = cyclicBarrier;
            this.taskNme = taskNme;
        }

        @Override
        public void run() {
            try {
                //模拟任务处理前的数据准备
                Thread.sleep(new Random().nextInt(3000));
                System.out.println(taskNme+ "准备OK!");
                cyclicBarrier.await();
                System.out.println(taskNme+"开始执行任务!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

        }
    }

    //主函数
    public static void main(String[] args) {
        //约定好3个准备好以后,才开始await()之后的操作
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);//修改成4
        //初始化容量为3个线程的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        executorService.submit(new MyTask(cyclicBarrier, "任务1"));
        executorService.submit(new MyTask(cyclicBarrier, "任务2"));
        executorService.submit(new MyTask(cyclicBarrier, "任务3"));

        executorService.shutdown();
    }
}

打印result:
这里写图片描述

如果把约定的线程数改为4个,那么你会发现任务准备好之后不会去执行await之后的代码,一直等待阻塞着:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/java_huilong/article/details/79031757