Статьи

Java Concurrency — пример CyclicBarrier

CyclicBarrier в Java — это синхронизатор, представленный в JDK 5 для пакета java.util.Concurrent вместе с другой параллельной утилитой, такой как Counting Semaphore , BlockingQueue , ConcurrentHashMap и т. Д. CyclicBarrier похож на CountDownLatch, который мы видели в прошлой статье, и позволяет нескольким потокам ожидать друг друга (барьер), прежде чем продолжить. Кроме того, разница между CoundDownLatch и CyclicBarrier также является очень популярным вопросом о многопоточности интервью в Java. CyclicBarrier является естественным требованием для параллельной программы, поскольку его можно использовать для выполнения заключительной части задачи после выполнения отдельных задач. Все потоки, которые ждут друг друга для достижения барьера, называются сторонами, CyclicBarrier инициализируется с количеством ожидающих сторон, а потоки ждут друг друга, вызывая метод CyclicBarrier.await (), который является методом блокировки в Java, и блокирует до тех пор, пока все потоки или стороны вызывают ожидание (). Вообще, вызов await () — это крик, что Thread ожидает барьера. await () является блокирующим вызовом, но может быть заблокирован по тайм-ауту или прерван другим потоком. В этом руководстве по параллелизму Java мы увидим простой пример CyclicBarrier, в котором три потока будут ждать друг друга, прежде чем продолжить.
Разница между CountDownLatch и CyclicBarrier в Java
В нашей последней статье мы увидели, как CountDownLatch можно использовать для реализации нескольких потоков, ожидающих друг друга. Если вы посмотрите на CyclicBarrier, то он тоже делает то же самое, но есть и другое, вы не можете повторно использовать CountDownLatch, когда счетчик достигнет нуля, в то время как вы можете повторно использовать CyclicBarrier, вызывая метод reset (), который сбрасывает Barrier в его начальное состояние. Что это означает, что CountDownLatch подходит для однократного события, такого как время запуска приложения, и CyclicBarrier можно использовать в случае повторяющегося события, например, для одновременного вычисления решения большой проблемы и т. Д. Если вы хотите узнать больше о многопоточности и параллелизме в Java, вы Можно также проверить мой пост о том, когда использовать переменную Volatile в Java и как работает синхронизация в Java .
CyclicBarrier в Java — пример
Вот простой пример CyclicBarrier в Java, на котором мы инициализируем CyclicBarrier с 3 сторонами, значит, для преодоления барьера 3 потоку необходимо вызвать метод await (). каждый поток вызывает метод await в течение короткого промежутка времени, но он не продолжается до тех пор, пока все 3 потока не достигнут барьера, как только все потоки достигнут барьера, барьер становится посредником, и каждый поток начинает выполнение с этой точки. Это очень ясно с выводом следующего примера CyclicBarrier в Java:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.logging.Level;
import java.util.logging.Logger;
 
/**
* Java program to demonstrate how to use CyclicBarrier in Java. CyclicBarrier is a
* new Concurrency Utility added in Java 5 Concurrent package.
*
* @author Javin Paul
*/
               
public class CyclicBarrierExample {
 
//Runnable task for each thread
private static class Task implements Runnable {
 
private CyclicBarrier barrier;
 
public Task(CyclicBarrier barrier) {
this.barrier = barrier;
}
 
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " is waiting on barrier");
barrier.await();
System.out.println(Thread.currentThread().getName() + " has crossed the barrier");
} catch (InterruptedException ex) {
Logger.getLogger(CyclicBarrierExample.class.getName()).log(Level.SEVERE, null, ex);
} catch (BrokenBarrierException ex) {
Logger.getLogger(CyclicBarrierExample.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
 
public static void main (String args[]) {
 
//creating CyclicBarrier with 3 parties i.e. 3 Threads needs to call await()
final CyclicBarrier cb = new CyclicBarrier(3, new Runnable(){
@Override
public void run(){
//This task will be executed once all thread reaches barrier
System.out.println("All parties are arrived at barrier, lets play");
}
});
 
//starting each of thread
Thread t1 = new Thread(new Task(cb), "Thread 1");
Thread t2 = new Thread(new Task(cb), "Thread 2");
Thread t3 = new Thread(new Task(cb), "Thread 3");
 
t1.start();
t2.start();
t3.start();
 
}
}

Выход:

1
2
3
4
5
6
7
Thread 1 is waiting on barrier
Thread 3 is waiting on barrier
Thread 2 is waiting on barrier
All parties are arrived at barrier, lets play
Thread 3 has crossed the barrier
Thread 1 has crossed the barrier
Thread 2 has crossed the barrier
Когда использовать CyclicBarrier в Java
Принимая во внимание характер CyclicBarrier, может быть очень удобно реализовать задачу типа «уменьшить карту», ​​аналогичную фреймворку Java 7 , в котором большая задача разбивается на более мелкие части, и для выполнения задачи вам необходим выход из отдельной небольшой задачи, например Для подсчета населения Индии у вас может быть 4 потока, которые подсчитывают население с Севера, Юга, Востока и Запада, и после завершения они могут ждать друг друга. Когда последний поток завершил свою задачу, Главный поток или любой другой поток может добавить результат из каждой зоны. и распечатать общее население. Вы можете использовать CyclicBarrier в Java:
1) Для реализации многопользовательской игры, которая не может начаться, пока все игроки не присоединились.
2) Выполните длительный расчет, разбив его на более мелкие индивидуальные задачи, в общем, для реализации техники сокращения карт.
Важный момент CyclicBarrier в Java
1. CyclicBarrier может выполнить задачу завершения, как только весь поток достигнет барьера. Это может быть обеспечено при создании CyclicBarrier.
2. Если CyclicBarrier инициализируется 3-мя сторонами, значит, 3-му потоку необходимо вызвать метод await для преодоления барьера.
3. Поток будет блокироваться в ожидании (), пока все стороны не достигнут барьера, другой поток не прервет или не истечет время ожидания.
4. Если другой поток прерывает ожидающий барьер поток, он выдаст исключение BrokernBarrierException, как показано ниже:
1
2
3
java.util.concurrent.BrokenBarrierException
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:172)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:327)
5. CyclicBarrier .reset () переводит Barrier в исходное состояние, другой поток, который ожидает или еще не достиг барьера, прекратит работу с java.util.concurrent.BrokenBarrierException.
Это все о CyclicBarrier в Java с примером. Мы также увидели разницу между CountDownLatch и CyclicBarrier в Java и получили представление о том, где мы можем использовать CyclicBarrier в Java. Параллельный код.

Ссылка: Пример CyclicBarrier в Java 5 — Учебник по параллелизу от нашего партнера по JCG Явина Пола в блоге Javarevisited .