我们在看田径比赛时,会有这样的场景:一群运动员先后到达起点准备,然后在一声枪响之后,所有运动员同时起跑,奔向终点。
在JAVA并发编程体系中,也有仿真的工具——CyclicBarrier。我们先来看看《JAVA编程思想第四版》中对于CyclicBarrier的解释:
CyclicBarrier适用于这样的情况:你希望新建一组任务,他们并行的执行任务,然后在进行下一步之前等待,
直到所有的任务都完成(看起来有些像join()),他使得所有的并行任务都将在栅栏处列队,因此可以一致的向前移动。
这非常像CountDownLatch,只是CountDownLatch是只触发一次的事件,而CyclicBarrier可以多次重用。
我们来看下具体的编程应用:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author 作者 John L:
* @version 创建时间:May 5, 2018 7:17:42 PM
*/
public class TestCyclicBarrier {
public static void main(String[] args) throws Exception{
int SIZE = 10;
//将需要等待的线程总数量传入
CyclicBarrier barrier = new CyclicBarrier(SIZE);
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
List<Runnable> threads = new ArrayList<Runnable>();
for (int i = 0; i < SIZE; i++) {
threads.add(new MyThread2(barrier));
}
for (Runnable runnable : threads) {
//每隔一秒开启一个线程
Thread.sleep(1000);
cachedThreadPool.execute(runnable);
}
System.out.println("main Thread--finished starting threads");
}
}
class MyThread2 implements Runnable{
private CyclicBarrier barrier = null;
private static int count = 0;
private final int id = count ++ ;
//所有这一组的线程都应该共享一个CyclicBarrier实例
public MyThread2(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
try {
System.out.println("线程 " + id + " 签到 ! " + System.currentTimeMillis());
//线程会在这里阻塞,直到在这里阻塞的线程总数量达到SIZE
//然后所有在这里阻塞的线程都会同时继续往下运行
barrier.await();
System.out.println("线程 " + id + " 开始工作 !" + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}
再看看console情况:
线程 0 签到 ! 1525523092569
线程 1 签到 ! 1525523093574
线程 2 签到 ! 1525523094586
线程 3 签到 ! 1525523095591
线程 4 签到 ! 1525523096600
线程 5 签到 ! 1525523097607
线程 6 签到 ! 1525523098616
线程 7 签到 ! 1525523099620
线程 8 签到 ! 1525523100622
main Thread--finished starting threads
线程 9 签到 ! 1525523101624
线程 9 开始工作 !1525523101624
线程 0 开始工作 !1525523101624
线程 3 开始工作 !1525523101624
线程 6 开始工作 !1525523101624
线程 8 开始工作 !1525523101624
线程 5 开始工作 !1525523101624
线程 4 开始工作 !1525523101624
线程 1 开始工作 !1525523101624
线程 2 开始工作 !1525523101624
线程 7 开始工作 !1525523101624
由控制台打印情况可知,每隔一秒钟左右,就会有一个线程到达await处签到等待,当线程9签到后,就满足了10等待线程的条件,于是所有这10个线程就同时起步,开始工作。这在最大程度上的保证了这10个线程会在同时开始 工作。