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

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() {

				@Override
				public 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,您想了解关于Java并发编程中的CountDownLatch吗? CountDownLatchJava并发编程中非常重要的一个工具类,它可以让某个线程等待其他线程完成后再继续执行。它的作用类似于倒计时门闩,当count值减为0时,所有等待者都会被唤醒。 CountDownLatch是一次性的,也就是说,它的计数器只能使用一次。如果需要重复使用,可以考虑使用CyclicBarrier。 在使用CountDownLatch时,我们需要先创建一个CountDownLatch对象,并指定计数器的初始值。然后在需要等待的线程中调用await()方法进行等待,同时在其他线程中调用countDown()方法进行计数器的减1操作。 举个例子,假设我们有一个需求:主线程需要等待两个子线程完成后再执行。那么可以这样编写代码: ```java import java.util.concurrent.CountDownLatch; public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(2); new Thread(() -> { System.out.println(Thread.currentThread().getName() + "执行开始"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "执行完毕"); countDownLatch.countDown(); }, "线程1").start(); new Thread(() -> { System.out.println(Thread.currentThread().getName() + "执行开始"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "执行完毕"); countDownLatch.countDown(); }, "线程2").start(); System.out.println(Thread.currentThread().getName() + "等待子线程执行完毕"); countDownLatch.await(); System.out.println(Thread.currentThread().getName() + "所有子线程执行完毕,继续执行主线程"); } } ``` 在上面的例子中,我们首先创建了一个计数器初始值为2的CountDownLatch对象,然后创建了两个线程分别进行一些操作,并在操作结束后调用countDown()方法进行计数器减1操作。在主线程中,我们调用await()方法进行等待,直到计数器减为0时,主线程才会继续执行。 希望能够对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值