15-Java5的CyclicBarrier同步工具
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
CyclicBarrier 支持一个可选的 Runnable
命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。
范例:有A、B、C三个人,他们约好周末去玩,计划各自先从家出发到集合点1集合,然后一起去集合点2吃饭,最后去集合点3唱歌。
注意:假设三个人都是各自开车去,有先后到达的情况。
package cn.itcast.demo.thread; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReentrantLock; public class CyclicBarrierTest { public static void main(String[] args) { // 创建锁 final ReentrantLock rtLock = new ReentrantLock(); // 创建线程池对象 ExecutorService executorService = Executors.newCachedThreadPool(); // 创建3个线程同步类对象【即3个线程到达之后才开始执行任务】 final CyclicBarrier cb = new CyclicBarrier(3); // 开启3个线程 for (int i=0; i<3; i++) { Runnable runnable = new Runnable() { @Override public void run() { try { rtLock.lock(); // 这是模拟线程从出发到到达集合点的过程的所花费的时间 Thread.sleep((long)Math.random()*10000); System.out.println("线程[ " + Thread.currentThread().getName() + " ]即将到达集合点1,当前已有[ " + (cb.getNumberWaiting()+1) + " ]个线程已经到达," + (cb.getNumberWaiting()==2?"人到齐了,继续走啊!":"正在等候...")); rtLock.unlock(); // 只有三个线程都到了集合点1之后才继续执行下面的代码,否则就await(),继续等待... cb.await(); rtLock.lock(); // 如果三个线程都到达了集合点1之后,才开始向集合点2出发 Thread.sleep((long)Math.random()*10000); System.out.println("线程[ " + Thread.currentThread().getName() + " ]即将到达集合点2,当前已有[ " + (cb.getNumberWaiting()+1) + " ]个线程已经到达," + (cb.getNumberWaiting()==2?"人到齐了,继续走啊!":"正在等候...")); rtLock.unlock(); // 同样,只有三个都到之后才会向集合点3出发,否则只能等待... cb.await(); rtLock.lock(); // 三个都到大集合点2之后,继续向集合点3出发 Thread.sleep((long)Math.random()*10000); System.out.println("线程[ " + Thread.currentThread().getName() + " ]即将到达集合点3,当前已有[ " + (cb.getNumberWaiting()+1) + " ]个线程已经到达," + (cb.getNumberWaiting()==2?"人到齐了,继续走啊!":"正在等候...")); } catch (Exception e) { e.printStackTrace(); } finally { rtLock.unlock(); try { cb.await(); } catch (Exception e) { e.printStackTrace(); } } } }; // 将每个线程添加到线程池中 executorService.execute(runnable); } // 结束所有线程 executorService.shutdown(); } }
打印结果:
线程[ pool-1-thread-1 ]即将到达集合点1,当前已有[ 1 ]个线程已经到达,正在等候... 线程[ pool-1-thread-3 ]即将到达集合点1,当前已有[ 2 ]个线程已经到达,正在等候... 线程[ pool-1-thread-2 ]即将到达集合点1,当前已有[ 3 ]个线程已经到达,人到齐了,继续走啊! 线程[ pool-1-thread-2 ]即将到达集合点2,当前已有[ 1 ]个线程已经到达,正在等候... 线程[ pool-1-thread-1 ]即将到达集合点2,当前已有[ 2 ]个线程已经到达,正在等候... 线程[ pool-1-thread-3 ]即将到达集合点2,当前已有[ 3 ]个线程已经到达,人到齐了,继续走啊! 线程[ pool-1-thread-3 ]即将到达集合点3,当前已有[ 1 ]个线程已经到达,正在等候... 线程[ pool-1-thread-2 ]即将到达集合点3,当前已有[ 2 ]个线程已经到达,正在等候... 线程[ pool-1-thread-1 ]即将到达集合点3,当前已有[ 3 ]个线程已经到达,人到齐了,继续走啊!