循环栅栏
作用:多线程间协调调度
场景:多线程间互相等待到达一公共栅栏位置后再继续执行。一般用于固定数量的线程间相互等待,在所有waiting的线程释放后,栅栏标记位被重置再利用。
与CountDownLatch的区别:CountDownLatch 一般用于不固定数量的线程间执行任务后计数,最终达到指定数量后,等待线程恢复执行,所以CountDownLatch被设计为只能一次性使用。
先看看这张模拟乘车场景图示:
示例程序:
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierTest {
public static void main(String[] args) {
String[] passengers = {"小明", "张三", "小王", "小李", "司机"};
CyclicBarrier barrier = new CyclicBarrier(passengers.length, new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " ---------------发车");
}
});
for (String name : passengers) {
new ByBusTask(barrier, name).start();
}
}
static class ByBusTask extends Thread {
CyclicBarrier barrier;
public ByBusTask(CyclicBarrier barrier, String name) {
super(name);
this.barrier = barrier;
}
@Override
public void run() {
try {
String name = getName();
CyclicBarrierTest.sleep(name);
System.out.println(name + " 上车去A站");
barrier.await();
System.out.println(name + " 到达A站下车");
CyclicBarrierTest.sleep(name);
System.out.println(name + " 上车去B站");
barrier.await();
System.out.println(name + " 到达B站下车");
} catch (Exception e) {
e.printStackTrace();
}
}
}
static void sleep(String name) {
try {
if (name.equals("司机")) {
Thread.sleep(2000);
} else {
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出结果:
张三 上车去A站
小李 上车去A站
小王 上车去A站
小明 上车去A站
司机 上车去A站
司机 ---------------发车
司机 到达A站下车
张三 到达A站下车
小明 到达A站下车
小李 到达A站下车
小王 到达A站下车
小明 上车去B站
小李 上车去B站
张三 上车去B站
小王 上车去B站
司机 上车去B站
司机 ---------------发车
司机 到达B站下车
小李 到达B站下车
小王 到达B站下车
张三 到达B站下车
小明 到达B站下车