在谈Java并发CountDownLatch与CyclicBarrier区别

CountDownLatch和CyclicBarrier都是控制并发而生,都在java.util.concurrent包下。

CountDownLatch

简单称为计数器,适合1个或者多个线程等待其他线程执行完毕后自己开始执行。其中最主要的方法是await和countDown,调用await()的线程如果CountDownLatch内部count变量不为0,则一直阻塞,直到为0,并且可以有多个线程调用await(),也就是多个线程同时等待。

下面的例子先创建两个线程,一直等待,然后启动10个线程对CountDownLatch进行减少。10次countDown()后,前两个线程才可以运行。

public class Main2 {
    static CountDownLatch countDownLatch = new CountDownLatch(10);

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 2; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread()+" start");
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread() + " end");

            }).start();
        }
        Thread.sleep(2000);
        startThreads();
    }

    private static void startThreads() {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                countDownLatch.countDown();
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

CyclicBarrier

和CountDownLatch类似,也实现了线程间的计数等待,同样调用其await()让线程阻塞,但是区别是只有当其他线程也调用await()直到数量为计数总数时才得到运行。并且提供了复位方法reset()。

比如和朋友开黑,5名朋友依次来网吧,来的人要等待没来的,到齐后,一起说声联盟万岁。

public class Main2 {
    public static void main(String[] args) throws InterruptedException {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(5, () -> {
            System.out.println("可以开黑了");
        });
        for (int i = 0; i < 5; i++) {
            new Friend(cyclicBarrier).start();
            System.out.println("还剩" + (cyclicBarrier.getParties() - cyclicBarrier.getNumberWaiting()) + " 人");
            Thread.sleep(1000);

        }
    }

    static class Friend extends Thread {
        CyclicBarrier mCyclicBarrier;

        public Friend(CyclicBarrier cyclicBarrier) {
            mCyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {
            super.run();
            String msg = (mCyclicBarrier.getParties() - mCyclicBarrier.getNumberWaiting() == 1) ? "最后一位到了" : "等待其他队友";
            System.out.println(Thread.currentThread() + msg);
            try {
                mCyclicBarrier.await();
                System.out.println("联盟万岁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}
还剩5 人
Thread[Thread-0,5,main]等待其他队友
还剩4 人
Thread[Thread-1,5,main]等待其他队友
还剩3 人
Thread[Thread-2,5,main]等待其他队友
还剩2 人
Thread[Thread-3,5,main]等待其他队友
还剩1 人
Thread[Thread-4,5,main]最后一位到了
可以开黑了
联盟万岁
联盟万岁
联盟万岁
联盟万岁
联盟万岁

区别

对于CountDownLatch,等待条件完成后执行者是其他线程,而CyclicBarrier是本身,并且CyclicBarrier可循环使用,提供了reset()来复位,但是会导致await()的线程抛出BrokenBarrierException异常。

也就是说CountDownLatch是一个或者多个线程在等待其他线程,而CyclicBarrier是多个线程互相等待。

发布了42 篇原创文章 · 获赞 7 · 访问量 7752

猜你喜欢

转载自blog.csdn.net/HouXinLin_CSDN/article/details/104193588
今日推荐