java同步工具类之CountDownLatch

本文介绍了 Java 中 CountDownLatch 类的应用场景及使用方法。通过两个实例演示了如何利用 CountDownLatch 控制多线程之间的等待与唤醒机制,包括等待特定条件或一定时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


    在一些应用场合中,某段程序需要等待某个条件达到要求后才能执行,或者等待一定长的时间后此行,从jdk1.5开始就可以使用CountDownLatch实现,    
    CountDownLatch类是一个同步倒数计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞后面程序执行,直到计数器为0。
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();

	}
}

             上面示例初始化两个CountDownLatch示例,分别传入初始值1和3,cdOrder.await()后面的代码,将会被阻塞,直到调用一次cdOrder.countDown()后才向下执行;cdAnswer.await()后面代码阻塞,调用三次cdAnswer.countDown()向下执行。

             所以上面执行结果:

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

await(long timeout, TimeUnit unit),是等待一定时间,然后执行,不管计数器是否到0了。

下面例子来源:http://www.blogjava.net/freeman1984/archive/2011/07/04/353654.html

10个同学上车,车等待同学上车,如果有等待时间限制,到时间就开走,不管学生上没上完。如果没有等待时间,学生上完了再开:

public class CountDownLatchTest {
    public static int numberOfPeople = 10;//等车的学生数
    public static boolean isGone = false;//车开的标志
    public static int carWaitTime = 3;//车等的时间
    
    public static void main(String[] args) throws InterruptedException {
        
        CountDownLatch waitStudentsGetOn = new CountDownLatch(numberOfPeople);
        
        new Thread(new GetOn(waitStudentsGetOn)).start();
        
        waitStudentGetOn(waitStudentsGetOn);//等所有的学生上车
        
        driveHome();//开车走
        
    }
    
    private static void waitStudentGetOn(CountDownLatch waitStudentsGetOn) throws InterruptedException {
        System.out.println("赶紧的,抓紧时间上车..");
        waitStudentsGetOn.await(carWaitTime, TimeUnit.SECONDS);//等5秒,还没上车,就开走。。
        
    }

    private static void driveHome() throws InterruptedException {
        System.out.println("开车,鞋儿破 帽儿破 身上的袈裟破 你笑我 他笑我 一把扇儿破");
        isGone = true;
        
    }
    
}
class GetOn implements Runnable{
    
    private CountDownLatch waitStudentsGetOn;
    GetOn(CountDownLatch waitStudentsGetOn){
        this.waitStudentsGetOn = waitStudentsGetOn;
    }
    public void run() {
        for (int i = 0; i < CountDownLatchTest.numberOfPeople; i++) {
            try {
                if(CountDownLatchTest.isGone){
                    System.out.println("妈的,还差:"+waitStudentsGetOn.getCount()+" 个没娃上车呢.怎么车走了");
                    break;
                }
                boolean goonSuccess = new Student(i+1).getOn();//顺序上车
                if(goonSuccess)waitStudentsGetOn.countDown();
            } catch (InterruptedException e) {}
                if(waitStudentsGetOn.getCount()!=0l){
                    System.out.println("还差:"+(waitStudentsGetOn.getCount())+" 个没上车");
                }else{
                    System.out.println("都上车了");
                }
        }
        
        
    }
    class Student{
        private int myNum;//学生编号
         public Student(int num){
                this.myNum = num;
          }
         //上车
         public boolean getOn() throws InterruptedException{
             Thread.currentThread().sleep(new Random().nextInt(2)*1000);//上车使用的时间,随机
             if(CountDownLatchTest.isGone){
                 return false;//不能上了,上车失败
             }
             System.out.print("编号为:"+myNum+"的同学上车了..");
             return true;
         }
    }
}


‘     


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值