java并发编程(12)--CyclicBarrier&CountDownLatch

来源:互联网 发布:windows网络编程模型 编辑:程序博客网 时间:2024/05/02 04:32

1.CyclicBarrier

public class CyclicBarrier
     

      extends
      Object
     

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

CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。


 方法摘要
 int     await()
          在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
 int     await(long timeout, TimeUnit unit)
          在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。
 int     getNumberWaiting()
          返回当前在屏障处等待的参与者数目。
 int     getParties()
          返回要求启动此 barrier 的参与者数目。
 boolean     isBroken()
          查询此屏障是否处于损坏状态。
 void     reset()
          将屏障重置为其初始状态。

列子:

package com.qunar.thread;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CycBarrierTest {public static void main(String[] args) {ExecutorService service = Executors.newCachedThreadPool();final CyclicBarrier cb = new CyclicBarrier(3);for (int i = 0; i < 3; i++) {Runnable runnable = new Runnable() {@Overridepublic void run() {try {Thread.sleep((long) Math.random() * 1000);System.out.println("线程:"+ Thread.currentThread().getName()+ ",已经到达地点一,当前已有"+ (cb.getNumberWaiting() + 1)+ "个线程到达集合地点"+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走": "正在等候"));cb.await();Thread.sleep((long) Math.random() * 1000);System.out.println("线程:"+ Thread.currentThread().getName()+ ",将要到达集合地点二,当前已经有"+ (cb.getNumberWaiting() + 1)+ "个线程到达集合地点"+ (cb.getNumberWaiting() == 2 ? "都到齐了,继续走": "正在等候"));cb.await();} catch (Exception e) {e.printStackTrace();}}};service.execute(runnable);}service.shutdown();}}


2.CountDownLatch

public class CountDownLatch


 一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。



 方法摘要
 void     await()
          使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
 boolean     await(long timeout, TimeUnit unit)
          使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
 void     countDown()
          递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
 long     getCount()
          返回当前计数。
 String     toString()
          返回标识此锁存器及其状态的字符串。



eg:

package com.qunar.thread;import java.util.concurrent.CountDownLatch;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CountdownLatchTest {public static void main(String[] args) {ExecutorService service = Executors.newCachedThreadPool();final CountDownLatch cdOrder = new CountDownLatch(1);final CountDownLatch cdAnswer = new CountDownLatch(3);for(int i=0;i<3;i++){Runnable runnable = new Runnable(){public void run(){try {System.out.println("线程" + Thread.currentThread().getName() + "正在准备接受命令");cdOrder.await();System.out.println("线程" + Thread.currentThread().getName() + "已接受命令");Thread.sleep((long)(Math.random()*10000));System.out.println("线程" + Thread.currentThread().getName() + "回应命令处理结束");cdAnswer.countDown();} catch (Exception e) {e.printStackTrace();}}};service.execute(runnable);}try {Thread.sleep((long)(Math.random()*10000));System.out.println("线程" + Thread.currentThread().getName() + "即将发布命令");cdOrder.countDown();System.out.println("线程" + Thread.currentThread().getName() + "已发出命令正等待结果");cdAnswer.await();System.out.println("线程" + Thread.currentThread().getName() + "已经收到所有响应结果");} catch (Exception e) {e.printStackTrace();}service.shutdown();}}

运行结果:
线程pool-1-thread-2正在准备接受命令线程pool-1-thread-3正在准备接受命令线程pool-1-thread-1正在准备接受命令线程main即将发布命令线程main已发出命令正等待结果线程pool-1-thread-3已接受命令线程pool-1-thread-1已接受命令线程pool-1-thread-2已接受命令线程pool-1-thread-2回应命令处理结束线程pool-1-thread-3回应命令处理结束线程pool-1-thread-1回应命令处理结束线程main已经收到所有响应结果










0 0
原创粉丝点击