package com.day20180312; import java.util.concurrent.CyclicBarrier; /** * CyclicBarrier(循环的栅栏) * eg:跑道准备+赛跑,会议室里等与会人员到齐了会议才能开始。 * 允许两个或者多个线程在某个集合点同步 * 构造方法: * public CyclicBarrier(int parties, Runnable barrierAction) { } public CyclicBarrier(int parties) { } 参数parties指让多少个线程或者任务等待至barrier状态; 参数barrierAction为当这些线程都达到barrier状态时会执行的内容。 CyclicBarrier中最重要的方法就是await方法 //挂起当前线程,直至所有线程都到达barrier状态再同时执行后续任务; public int await() throws InterruptedException, BrokenBarrierException { }; //让这些线程等待至一定的时间,如果还有线程没有到达barrier状态就直接让到达barrier的线程执行后续任务 public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { }; * @author jeff * 2018年3月26日 */ public class TestCyclicBarrier { public static void main(String[] args) throws InterruptedException { CyclicBarrier cyclicBarrier = new CyclicBarrier(10, new Runnable() { @Override public void run() { System.out.println("10个线程都已经准备完毕!3...2...1...哨响!开始赛跑!"); } }); for (int i = 0; i < 10; i++) { new Thread(new readNum(i, cyclicBarrier)).start(); } // CyclicBarrier 可以重复利用, // 这个是CountDownLatch做不到的 // for (int i = 11; i < 16; i++) { // new Thread(new readNum(i,cyclicBarrier)).start(); // } } static class readNum implements Runnable { private int id; private CyclicBarrier cyc; public readNum(int id, CyclicBarrier cyc) { this.id = id; this.cyc = cyc; } @Override public void run() { synchronized (this) { System.out.println("线程" + id + "开始准备出发"); try { cyc.await(); System.out.println("线程" + id + "已到达终点.,其他任务继续"); } catch (Exception e) { e.printStackTrace(); } } } } }
控制台打印结果:
线程0开始准备出发 线程1开始准备出发 线程2开始准备出发 线程4开始准备出发 线程3开始准备出发 线程8开始准备出发 线程7开始准备出发 线程9开始准备出发 线程5开始准备出发 线程6开始准备出发 10个线程都已经准备完毕!3...2...1...哨响!开始赛跑! 线程6已到达终点.,其他任务继续 线程0已到达终点.,其他任务继续 线程1已到达终点.,其他任务继续 线程4已到达终点.,其他任务继续 线程3已到达终点.,其他任务继续 线程2已到达终点.,其他任务继续 线程9已到达终点.,其他任务继续 线程7已到达终点.,其他任务继续 线程8已到达终点.,其他任务继续 线程5已到达终点.,其他任务继续
CyclicBarrier和CountDownLatch 都位于java.util.concurrent 这个包下:
CountDownLatch | CyclicBarrier |
减计数方式 | 加计数方式 |
计算为0时释放所有等待的线程 | 计数达到指定值时释放所有等待线程 |
计数为0时,无法重置 | 计数达到指定值时,计数置为0重新开始 |
调用countDown()方法计数减一,调用await()方法只进行阻塞,对计数没任何影响 | 调用await()方法计数加1,若加1后的值不等于构造方法的值,则线程阻塞 |
不可重复利用 | 可重复利用 |
强调一个线程等多个线程完成某件事情 | CyclicBarrier是多个线程互等,等大家都完成.................. |