Java多线程 并发编程

CountDownLatch(闭锁) 与 CyclicBarr

2018-08-06  本文已影响8人  SHAN某人

1. 闭锁

闭锁是 J.U.C包下的一个同步组件。

闭锁,图从上往下看,countDown方法计数器减1

作用:

被等待线程调用countdown方法计数器减1,减到0时等待线程(调用await方法的线程)被唤醒。

一个闭锁工作起来就像一道大门:直到闭锁达到终点状态之前,门一直是关闭的,没有线程通过,在终点状态到来的时候,门开了,允许所有线程都通过。一旦闭锁到达了终点状态,他就不能够在改变状态了,所以它会永远保持敞开的状态。

适用场景

1.确保一个计算不会执行,直到它需要的资源被初始化。
2.确保一个服务不会开始,直到它依赖的服务都已经开始。
3.等待直到活动的所有部分都为继续处理做好准备。比如王者荣耀需要等待所有玩家准备才能开始。

代码实例

public class CountDownLatchExample1 {

    private final static int threadCount = 200;

    public static void main(String[] args) throws Exception {

        ExecutorService exec = Executors.newCachedThreadPool();

        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            exec.execute(() -> {
                try {
                    test(threadNum);
                } catch (Exception e) {
                    log.error("exception", e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        countDownLatch.await();
        log.info("finish");
        exec.shutdown();
    }

    private static void test(int threadNum) throws Exception {
        Thread.sleep(100);
        log.info("{}", threadNum);
        Thread.sleep(100);
    }
}

2. 栅栏

图从下往上看,await方法计数器加1

CyclicBarrier 字面意思是回环栅栏,回环的意思是它能够被重复利用,当然前提是在所有线程释放了以后。

作用

栅栏描述的是线程间的相互等待,相互等待的线程都准备好就可以继续下去了。而且栅栏的计数器可以重置,这样意味着其中有线程准备过程执行失败可以全部重新准备。

比较

能否复用 场景
CountDownLatch 计数器不能重置 一个或者多个线程等待其他线程执行完成
CyclicBarrier 计数器可以重置 一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行

代码实例

public class CyclicBarrierExample1 {

    private static CyclicBarrier barrier = new CyclicBarrier(5);

    public static void main(String[] args) throws Exception {

        ExecutorService executor = Executors.newCachedThreadPool();
        // 十个线程
        for (int i = 0; i < 10; i++) {
            final int threadNum = i;
            Thread.sleep(1000);
            executor.execute(() -> {
                try {
                    race(Thread.currentThread().getName());
                } catch (Exception e) {
                    System.out.println("exception "+ e);
                }
            });
        }
        executor.shutdown();
    }

    private static void race(String threadNum) throws Exception {
        Thread.sleep(1000);
        System.out.printf("%s is ready \n", threadNum);
        barrier.await();
        System.out.printf("%s continue \n", threadNum);
    }
}

参考链接:
https://www.jianshu.com/p/79f95bb81c67
https://www.jianshu.com/p/5812bb54c44f

上一篇 下一篇

猜你喜欢

热点阅读