线程同步工具之CyclicBarrier

来源:互联网 发布:wine mac下载 编辑:程序博客网 时间:2024/05/16 13:55

CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。

  CyclicBarrier类似于CountDownLatch也是个计数器, 不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数, 当线程数达到了CyclicBarrier初始时规定的数目时,所有进入等待状态的线程被唤醒并继续。 CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。 CyclicBarrier初始时还可带一个Runnable的参数,此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。

构造方法摘要CyclicBarrier(int parties)
          创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在每个 barrier 上执行预定义的操作。CyclicBarrier(int parties,Runnable barrierAction)
          创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行

 

方法摘要intawait()
          在所有参与者都已经在此 barrier 上调用await 方法之前,将一直等待。intawait(long timeout,TimeUnit unit)
          在所有参与者都已经在此屏障上调用await 方法之前,将一直等待。intgetNumberWaiting()
          返回当前在屏障处等待的参与者数目。intgetParties()
          返回要求启动此 barrier 的参与者数目。booleanisBroken()
          查询此屏障是否处于损坏状态。voidreset()

          将屏障重置为其初始状态

以上转载于:http://www.cnblogs.com/liuling/archive/2013/08/21/2013-8-21-01.html

一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)  

public class Worker implements Runnable {final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");CyclicBarrier barrier;int workTime;public Worker(int workTime, CyclicBarrier barrier) {this.barrier = barrier;this.workTime = workTime;}public void run() {try {System.out.println(Thread.currentThread().getName() + " :等待: " + sdf.format(new Date()));// 模拟工作Thread.sleep(workTime);// 到此如果没有达到公共屏障点,则该线程处于等待状态,// 如果达到公共屏障点则所有处于等待的线程都继续往下运行barrier.await();} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " :完成: " + sdf.format(new Date()));}public static void main(String[] args) {CyclicBarrier barrier = new CyclicBarrier(3);// 即使传入时间不一样,也会等待时间长的完成才能继续进行Worker w1 = new Worker(3000, barrier);Worker w2 = new Worker(5000, barrier);Worker w3 = new Worker(2000, barrier);new Thread(w1, "线程1").start();new Thread(w2, "线程2").start();new Thread(w3, "线程3").start();}}
运行结果

线程3 :等待: 2017-04-15 12:15:17线程1 :等待: 2017-04-15 12:15:17线程2 :等待: 2017-04-15 12:15:17线程3 :完成: 2017-04-15 12:15:22线程2 :完成: 2017-04-15 12:15:22线程1 :完成: 2017-04-15 12:15:22
CyclicBarrier还提供一个更高级的构造函数CyclicBarrier(int parties, Runnable barrierAction),用于在线程到达屏障时,优先执行barrierAction,
public class Worker implements Runnable {final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");CyclicBarrier barrier;int workTime;public Worker(int workTime, CyclicBarrier barrier) {this.barrier = barrier;this.workTime = workTime;}public void run() {try {System.out.println(Thread.currentThread().getName() + " :等待: " + sdf.format(new Date()));// 模拟工作Thread.sleep(workTime);// 到此如果没有达到公共屏障点,则该线程处于等待状态,// 如果达到公共屏障点则所有处于等待的线程都继续往下运行barrier.await();} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " :完成: " + sdf.format(new Date()));}public static void main(String[] args) {/////////CyclicBarrier barrier = new CyclicBarrier(3,new Runnable() {@Overridepublic void run() {System.out.println("这是Runnable barrierAction……");}});// 即使传入时间不一样,也会等待时间长的完成才能继续进行Worker w1 = new Worker(3000, barrier);Worker w2 = new Worker(5000, barrier);Worker w3 = new Worker(2000, barrier);new Thread(w1, "线程1").start();new Thread(w2, "线程2").start();new Thread(w3, "线程3").start();}}
结果
线程2 :等待: 2017-04-15 12:18:42线程1 :等待: 2017-04-15 12:18:42线程3 :等待: 2017-04-15 12:18:42这是Runnable barrierAction……线程1 :完成: 2017-04-15 12:18:47线程3 :完成: 2017-04-15 12:18:47线程2 :完成: 2017-04-15 12:18:47
除了常见的异常,CyclicBarrier.await() 方法会抛出一个独有的 BrokenBarrierException。这个异常发生在当某个线程在等待本 CyclicBarrier 时被中断或超时或被重置时,其它同样在这个 CyclicBarrier 上等待的线程便会受到 BrokenBarrierException。意思就是说,同志们,别等了,有个小伙伴已经挂了,咱们如果继续等有可能会一直等下去,所有各回各家吧。CyclicBarrier.await() 方法带有返回值,用来表示当前线程是第几个到达这个 Barrier 的线程。

CountDownLatch的计数器只能使用一次。而CyclicBarrier的计数器可以使用reset() 方法重置。

注意CountDownLatch是阻塞主线程,而CyclicBarrier阻塞子线程

模拟循环使用

public class Worker implements Runnable {final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");CyclicBarrier barrier;int workTime;public Worker(int workTime, CyclicBarrier barrier) {this.barrier = barrier;this.workTime = workTime;}public void run() {try {System.out.println(Thread.currentThread().getName() + " :等待: " + sdf.format(new Date()));// 模拟工作Thread.sleep(workTime);// 到此如果没有达到公共屏障点,则该线程处于等待状态,// 如果达到公共屏障点则所有处于等待的线程都继续往下运行barrier.await();} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " :完成: " + sdf.format(new Date()));}public static void main(String[] args) throws InterruptedException {/////////CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {@Overridepublic void run() {System.out.println("这是Runnable barrierAction……");}});// 即使传入时间不一样,也会等待时间长的完成才能继续进行Worker w1 = new Worker(3000, barrier);Worker w2 = new Worker(4000, barrier);Worker w3 = new Worker(2000, barrier);new Thread(w1, "线程1").start();new Thread(w2, "线程2").start();new Thread(w3, "线程3").start();//模拟循环使用Thread.sleep(6000);System.out.println("---------------");barrier.reset();new Thread(w1, "线程1").start();new Thread(w2, "线程2").start();new Thread(w3, "线程3").start();}}

线程1 :等待: 2017-04-15 12:30:30线程3 :等待: 2017-04-15 12:30:30线程2 :等待: 2017-04-15 12:30:30这是Runnable barrierAction……线程2 :完成: 2017-04-15 12:30:34线程3 :完成: 2017-04-15 12:30:34线程1 :完成: 2017-04-15 12:30:34---------------线程2 :等待: 2017-04-15 12:30:36线程1 :等待: 2017-04-15 12:30:36线程3 :等待: 2017-04-15 12:30:36这是Runnable barrierAction……线程2 :完成: 2017-04-15 12:30:40线程3 :完成: 2017-04-15 12:30:40线程1 :完成: 2017-04-15 12:30:40
参考: 线程同步工具之CountDownLatch





0 0
原创粉丝点击