CyclicBarrier介绍
CyclicBarrier主要是一个实现可循环屏障的工具类,比如设置5个线程运行才可以主线程操作。可以使用在关联数据的批量处理
CyclicBarrier基本使用
package com.juc;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* @author:yangb
* @Date: 2019/9/22 10:17
* @Description: 栅栏
*/
public class CycliBarrierDemo extends Thread{
@Override
public void run() {
System.out.println("开始进行数据分析");
}
//循环屏障 使得一组线程到达一个同步点之前阻塞
public static void main(String[] args) {
CyclicBarrier cyclicBarrier=new CyclicBarrier(3,new CycliBarrierDemo());
new Thread( new DataImprotThread(cyclicBarrier,"file1")).start();
new Thread( new DataImprotThread(cyclicBarrier,"file2")).start();
new Thread( new DataImprotThread(cyclicBarrier,"file3")).start();
new Thread( new DataImprotThread(cyclicBarrier,"file4")).start();
}
static class DataImprotThread extends Thread {
private CyclicBarrier cyclicBarrier;
private String path;
public DataImprotThread( CyclicBarrier cyclicBarrier,String path){
this.cyclicBarrier=cyclicBarrier;
this.path=path;
}
@Override
public void run() {
System.out.println("开始导入"+path+"数据");
//TODO
try{
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
CyclicBarrier主要API
CyclicBarrier.await()
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;//获得锁对象
lock.lock();//加锁
try {
final Generation g = generation; //该对象中就一个boolean值 broken = false;
if (g.broken) //首次肯定不会抛出异常
throw new BrokenBarrierException();
if (Thread.interrupted()) { //判断线程是否中断过
breakBarrier(); //将broken 更改为true 更改count。释放Candition队列
throw new InterruptedException();
}
int index = --count; //等待数自减后赋值给index
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration(); //Candition队列放行,conut=parties,重置generation
return 0;
} finally {
if (!ranAction)
breakBarrier(); //将broken 更改为true 更改count。释放Candition队列
}
}
//日常自旋
for (;;) {
try { //因为有阻塞过程所以需要try catch
if (!timed) //在初始过程传的flase。
trip.await(); //调用Condition队列的await()方法,将当前线程加入Condition队列
else if (nanos > 0L) //初始值为0
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) { //阻塞异常
if (g == generation && ! g.broken) { //进行检测Generation是不是初始状态,是则运行breakBarrier()方法
breakBarrier(); //设置当前屏障以及被打破,唤醒所有线程。
throw ie;
} else {
Thread.currentThread().interrupt();//中断当前线程
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock(); //解锁
}
}
通过阅读源码 CyclicBarrier的核心就是借用Condition来进行阻塞,利用Generation来实现栅栏效果,通过对Generation.broken的状态来决定是否进行释放阻塞线程,parties进行阻塞计数,是一个比较简单的工具类。