определение
CountDownLatch: средство синхронизации, которое позволяет одному или нескольким потокам ожидать завершения набора операций, выполняемых в других потоках.
CyclicBarrier: вспомогательное средство синхронизации, позволяющее всем потокам ожидать друг друга для достижения общей точки барьера.
Выше приведено официальное определение Oracle. Проще говоря
CountDownLatch: счетчик, который позволяет одному или нескольким потокам ожидать завершения набора операций, выполняемых в других потоках.
CyclicBarrier: циклический барьер, который позволяет группе потоков ждать, пока друг друга не достигнут общей точки барьера.
разница
- CountDownLatch является членом AQS (AbstractQueuedSynchronizer), а CyclicBarrier — нет.
- В сценарии использования CountDownLatch существует два типа потоков: один — ожидающий поток, вызывающий метод await(), а другой — рабочий поток, вызывающий метод countDownl(). В сценарии CyclicBarrier существует только один тип потока, который представляет собой ожидающие потоки, ожидающие друг друга.
- CountDownLatch ведет обратный отсчет и не может быть сброшен после уменьшения, CyclicBarrier считает вверх и сбрасывается автоматически после увеличения
Пример обратного отсчета
- Создайте две группы потоков, одна группа ожидает завершения другой группы, прежде чем продолжить
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..
- Подождите, пока поток накопления завершит выполнение, а затем основной поток выведет результат накопления.
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..