CountDownLatch和CyclicBarriar是java.util.concurrent包下面提供的多线程同步工具,二者有点类似,至关于计数器,可是用处仍是有区别的。java
CountDownLatch:用于在完成一组正在其它线程中执行的操做以前,它容许一个或多个线程一直等待,await()表示等待,等到其它线程所有执行结束后(即经过countDown()方法来减数,计数为0,即其它线程执行完毕)而后继续执行,示例代码:多线程
public static void main(String[] args) { //该计数器初始值1,用于主线程发送命令 final CountDownLatch latch1 = new CountDownLatch(1); //该计数器初始值为2,用于响应命令接受完成 final CountDownLatch latch2 = new CountDownLatch(2); //建立一个大小为2线程池 ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i < 2; i++) { executor.submit(new Runnable() { public void run() { try { System.out.println("线程" + Thread.currentThread().getName() + "正准备接受命令"); //等待主线程发送命令 latch1.await(); System.out.println("线程" + Thread.currentThread().getName() + "已接受命令"); Thread.sleep((long) (Math.random() * 10000)); System.out.println("线程" + Thread.currentThread().getName() + "回应命令处理结果"); //命令接受完毕,返回给主线程,latch2减1。 latch2.countDown(); } catch (Exception e) { e.printStackTrace(); } } }); } try { Thread.sleep((long) (Math.random() * 10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将发布命令"); //发送命令,latch1计数减1 latch1.countDown(); System.out.println("线程" + Thread.currentThread().getName() + "已发送命令,正在等待响应"); //命令发送后处于等待状态,其它线程所有响应完成,也就是latch2.countDown(),再继续执行 latch2.await(); System.out.println("线程" + Thread.currentThread().getName() + "已收到全部响应结果"); } catch (Exception e) { e.printStackTrace(); } //关闭线程池 executor.shutdown(); }
CyclicBarriar:用于多个线程在一个指定的公共屏障点(或者说集合点)相互等待,await()方法表明屏障点,每次调用await(),计数(建立CyclicBarriar对象时传入int类型的参数,表示初始计数)减一,直到减到0后,表示全部线程都抵达,而后开始执行后面的任务,示例代码:dom
public static void main(String[] args) throws Exception { //建立CyclicBarrier对象并设置2个公共屏障点 final CyclicBarrier barrier = new CyclicBarrier(2); //建立大小为2的线程池 ExecutorService executor = Executors.newFixedThreadPool(2); for (int i = 0; i < 2; i++) { executor.submit(new Runnable() { public void run() { try { Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点1,当前已有" + barrier.getNumberWaiting() + "个已经到达,正在等候"); //若是没有达到公共屏障点,则该线程处于阻塞状态,若是达到公共屏障点则全部处于等待的线程都继续往下运行 barrier.await(); System.out.println("线程" + Thread.currentThread().getName() + "经过集合地点1"); Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点2,当前已有" + barrier.getNumberWaiting() + "个已经到达,正在等候"); barrier.await(); System.out.println("线程" + Thread.currentThread().getName() + "经过集合地点2"); } catch (Exception e) { e.printStackTrace(); } } }); } //关闭线程池 executor.shutdown(); }
注意:观察CyclicBarrier的使用能够发现,它计数减至0后,计数器会被重置,能够再次使用,可能这也是它被定义为Cyclic(周期的、循环的)缘由,这个是和CountDownLatch区别的地方。工具