1. Что умеет CyclicBarrier
Как и CountDownLatch, CyclicBarrier также является классом в составе пакета java.util.concurrent; как видно из имени класса, это барьер (Barrier), который можно переработать (Cylcic), и что он делает, так это позволяет группе потоков для достижения Барьер (точка синхронизации) блокируется до тех пор, пока последний поток в группе не достигнет барьера, барьер не будет открыт, а ранее заблокированный поток продолжит работу. Процесс показан на рисунке ниже
В каждом из трех потоков, показанных на рисунке выше, имеется по одному барьеру. ожидание. Когда какой-либо поток запускается к барьеру. ожидание, он входит в состояние ожидания блокировки. Он не вернется из ожидания, пока все три потока не достигнут барьера. ожидание и не продолжится. бежать назад..
2. Как использовать CyclicBarrier
При создании экземпляра объекта CyclicBarrier установите объем данных потока, который должен быть перехвачен барьером (количество вызовов барьера. ожидание) через его конструктор.Каждый поток сообщает CyclicBarrier, что я достиг барьера, вызывая метод ожидания. экземпляра CyclicBarrier и заблокирует себя.
Кроме того, если при создании CyclicBarrier установлена реализация Runnable, поток последнего барьера.
CyclicBarrier часто используется для многопоточных вычислений данных и, наконец, для слияния результатов вычислений. Например, лист Excel записывает весь банковский поток пользователя за квартал, а каждый лист записывает банковский поток пользователя каждый месяц.Чтобы подсчитать банковский поток пользователя за весь квартал, вы можете сначала использовать мульти- потоки для подсчета каждого листа.После выполнения банковского потока пользователя результат расчета каждого потока используется для расчета состояния банковского потока пользователя за весь квартал.
public class CyclicBarrierTest implements Runnable{
/*创建一个CyclicBarrier实例,屏障数据设为3,处理完之后执行当前类的run方法*/
private CyclicBarrier cb = new CyclicBarrier(3,this);
/*创建线程池,只有三个月的数据,所以只需三个线程*/
private Executor executor = Executors.newFixedThreadPool(3);
/*创建一个ConcurrentHashMap,用来保存每个sheet计算出的结果*/
private ConcurrentHashMap<String,Integer> sheetBankWaterCount = new ConcurrentHashMap<String, Integer>();
public void count() {
for(int i = 0;i<3;i++){
/*每个线程用来处理单个sheet中的任务*/
executor.execute(new Runnable() {
public void run() {
/*此处加入复杂的逻辑处理代码*/
sheetBankWaterCount.put(Thread.currentThread().getName(),1);
try {
/*线程完成工作后调用await 设置屏障*/
cb.await();
}catch (BrokenBarrierException e){
e.printStackTrace();
}catch (InterruptedException e){
e.printStackTrace();
}
}
});
}
}
/*等到所有的线程到达屏障*/
public void run() {
int res = 0;
/*根据之前多线程的结果计算出整个季度的银行流水*/
for (Map.Entry<String,Integer> sheet: sheetBankWaterCount.entrySet()) {
res += sheet.getValue();
}
sheetBankWaterCount.put("result",res);
/*将结果输出*/
System.out.println(res);
}
public static void main(String[] args){
CyclicBarrierTest test = new CyclicBarrierTest();
/*注意,此时不需要调用test.run(),最后一个await方法会调用run方法*/
test.count();
}
}
3. Вопросы, требующие внимания при использовании CyclicBarrier
При использовании CyclicBarrier в пуле потоков следует учитывать, что количество потоков превышает количество заблокированных потоков, заданное в экземпляре CyclicBarrier, и возникает взаимоблокировка. Количество вызовов метода await() должно быть равно количеству заблокированных потоков, заданному в барьере, иначе он также заблокируется.
В-четвертых, разница между CyclicBarrier и CountDownLatch
- Прежде всего, оба они могут блокировать и ждать один или несколько потоков, и оба могут использоваться для координации между несколькими потоками и играть роль синхронизации потоков. Однако CountDownLatch запускает время после того, как несколько потоков выполнили countDown, пробуждает поток, ожидающий защелки, и продолжает работу своего собственного потока после выполнения операции countDown. CyclicBarrier — это барьер, который используется для синхронизации всех потоков, вызывающих метод await.После того, как все методы выполнили метод await, все потоки вернутся, чтобы выполнить свою собственную работу.
- Счетчик CountDownLatch можно использовать только один раз, а счетчик CyclicBarrier можно сбросить, вызвав метод reset(), который может обрабатывать более сложные бизнес-сценарии.
Как одновременно использовать CountDownLatch в Java
Руководство по использованию семафоров для параллельного программирования на Java