CountDownLatch против CyclicBarrier

определение

CountDownLatch: средство синхронизации, которое позволяет одному или нескольким потокам ожидать завершения набора операций, выполняемых в других потоках.
CyclicBarrier: вспомогательное средство синхронизации, позволяющее всем потокам ожидать друг друга для достижения общей точки барьера.

Выше приведено официальное определение Oracle. Проще говоря

CountDownLatch: счетчик, который позволяет одному или нескольким потокам ожидать завершения набора операций, выполняемых в других потоках.
CyclicBarrier: циклический барьер, который позволяет группе потоков ждать, пока друг друга не достигнут общей точки барьера.

разница

  • CountDownLatch является членом AQS (AbstractQueuedSynchronizer), а CyclicBarrier — нет.
  • В сценарии использования CountDownLatch существует два типа потоков: один — ожидающий поток, вызывающий метод await(), а другой — рабочий поток, вызывающий метод countDownl(). В сценарии CyclicBarrier существует только один тип потока, который представляет собой ожидающие потоки, ожидающие друг друга.
  • CountDownLatch ведет обратный отсчет и не может быть сброшен после уменьшения, CyclicBarrier считает вверх и сбрасывается автоматически после увеличения

Пример обратного отсчета

  1. Создайте две группы потоков, одна группа ожидает завершения другой группы, прежде чем продолжить
CountDownLatch countDownLatch = new CountDownLatch(5);
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
    
    
    executorService.execute(() -> {
    
    
        countDownLatch.countDown();
        System.out.println("run..");
    });
}
for (int i = 0; i < 3; i++) {
    
      //我们要等上面执行完成才继续
    executorService.execute(() -> {
    
    
        try {
    
    
            countDownLatch.await();
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        System.out.println("await..");
    });
}
executorService.shutdown();

Распечатать:

run..
run..
run..
run..
run..
await..
await..
await..
  1. Подождите, пока поток накопления завершит выполнение, а затем основной поток выведет результат накопления.
public class ThreadUnsafeExample {
    
    

    private int cnt = 0;
    
    public void add() {
    
    
        cnt++;
    }

    public int get() {
    
    
        return cnt;
    }

    public static void main(String[] args) throws InterruptedException {
    
    
        final int threadSize = 1000;
        ThreadUnsafeExample example = new ThreadUnsafeExample();
        final CountDownLatch countDownLatch = new CountDownLatch(threadSize);
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < threadSize; i++) {
    
    
            executorService.execute(() -> {
    
    
                example.add();
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        executorService.shutdown();
        System.out.println(example.get());
    }
}

Распечатать:

997
  • 3 Симуляция параллелизма
ExecutorService executorService = Executors.newCachedThreadPool();
        CountDownLatch countDownLatch = new CountDownLatch(1);
        for (int i = 0; i < 5; i++) {
    
    
            executorService.submit( () -> {
    
    
                try {
    
    
                    countDownLatch.await();
                    System.out.println("【" + Thread.currentThread().getName() + "】开始执行……");
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            });
        }
        Thread.sleep(2000);
        countDownLatch.countDown();//开始并发
        executorService.shutdown();

Распечатать:

【pool-2-thread-2】开始执行……
【pool-2-thread-5】开始执行……
【pool-2-thread-3】开始执行……
【pool-2-thread-1】开始执行……
【pool-2-thread-4】开始执行……

Пример циклического барьера

  • Все потоки ждут друг друга, пока не будет завершен определенный шаг, прежде чем продолжить выполнение
        final int totalThread = 3;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < totalThread; i++) {
    
    
            executorService.execute(() -> {
    
    
                System.out.println("before..");
                try {
    
    
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
    
    
                    e.printStackTrace();
                }
                System.out.println("after..");
            });
        }
        executorService.shutdown();

Распечатать:

before..
before..
before..
after..
after..
after..

Guess you like

Origin blog.csdn.net/mryang125/article/details/125553912