首页 > 代码库 > 多线程 - CyclicBarrier
多线程 - CyclicBarrier
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
CyclicBarrier 支持一个可选的 Runnable
命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。
示例用法:下面是一个在并行分解设计中使用 barrier 的例子:
1 class Solver { 2 final int N; 3 final float[][] data; 4 final CyclicBarrier barrier; 5 6 class Worker implements Runnable { 7 int myRow; 8 Worker(int row) { myRow = row; } 9 public void run() { 10 while (!done()) { 11 processRow(myRow); 12 13 try { 14 barrier.await(); 15 } catch (InterruptedException ex) { 16 return; 17 } catch (BrokenBarrierException ex) { 18 return; 19 } 20 } 21 } 22 } 23 24 public Solver(float[][] matrix) { 25 data =http://www.mamicode.com/ matrix; 26 N = matrix.length; 27 barrier = new CyclicBarrier(N, 28 new Runnable() { 29 public void run() { 30 mergeRows(...); 31 } 32 }); 33 for (int i = 0; i < N; ++i) 34 new Thread(new Worker(i)).start(); 35 36 waitUntilDone(); 37 } 38 }
在这个例子中,每个 worker 线程处理矩阵的一行,在处理完所有的行之前,该线程将一直在屏障处等待。处理完所有的行之后,将执行所提供的 Runnable
屏障操作,并合并这些行。如果合并者确定已经找到了一个解决方案,那么 done() 将返回 true,所有的 worker 线程都将终止。
如果屏障操作在执行时不依赖于正挂起的线程,则线程组中的任何线程在获得释放时都能执行该操作。为方便此操作,每次调用 await()
都将返回能到达屏障处的线程的索引。然后,您可以选择哪个线程应该执行屏障操作,例如:
if (barrier.await() == 0) { // log the completion of this iteration }
对于失败的同步尝试,CyclicBarrier 使用了一种快速失败的、要么全部要么全不 (all-or-none) 的破坏模式:如果因为中断、失败或者超时等原因,导致线程过早地离开了屏障点,那么其他所有线程(甚至是那些尚未从以前的 await()
中恢复的线程)也将通过 BrokenBarrierException
(如果它们几乎同时被中断,则用 InterruptedException)以反常的方式离开。
多线程 - CyclicBarrier