java.util.concurrent.CountDownLatch用法

CountDownLatch类是java并发包的一个辅助实现线程协作的类。其内部是通过Sync内部类有一个volatile int state属性用于表示同步器的状态,其主要的两个方法是await()和countDown()。其中await的API描述为:  

Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted. 
引起当前线程等待,直到线程闩latch已经减小到0,除非线程被中断。
If the current count is zero then this method returns immediately. 
如果当前count是0,那么这个方法立即返回
If the current count is greater than zero then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of two things happen: 
如果当前count大于0,那么当前线程禁止线程调度,保持休眠直到下面的两件事之一发生:
The count reaches zero due to invocations of the countDown method; or 
Some other thread interrupts the current thread. 
1、由于调用countDown方法使count减小到0
2、其他的线程终止了该线程
<pre name="code" class="java">If the current thread:
has its interrupted status set on entry to this method; or is interrupted while waiting, then InterruptedException is thrown and the current thread's interrupted status is cleared.如果当前线程设置了中断状态,或者等待时被中断,那么将会派出InterruptedException异常,当前线程的中断状态也被清除

 countDown()方法的API描述为: 


Decrements the count of the latch, releasing all waiting threads if the count reaches zero. 
减小线程闩的数量,如果减少到0,则释放所有正在等待的线程
If the current count is greater than zero then it is decremented. If the new count is zero then all waiting threads are re-enabled for thread scheduling purposes. 
如果当前线程闩的数量大于0,那么数量就会减1。如果减1后的新值等于0,那么所有等待的线程都会重新允许线程调度。
If the current count equals zero then nothing happens.
如果当前线程等于0,那么将当啥事也没发生吧。
从API的描述可以看出,CountDownLatch主要是用于线程间的协作,保证一个线程或者多个线程等待其他线程到达指定位置。可以为其设定一个参数count来指定需要多少次countDown操作来唤醒等待中的线程。下面的例子给出了一种用法。
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
	private static CountDownLatch count = new CountDownLatch(1);
	public static void main(String[] args) {
		doStuff();
	}
	public static void doStuff(){
		//创建3个线程,并启动,但是每个线程当输出到5时,就停止等待线程闩
		for(int i = 0 ; i<3; i++){
			new Thread(){
				public void run(){
					
					for(int j = 0; j<10; j++){
						if( j==5){
							try {
								count.await();
							} catch (InterruptedException e) {
								System.out.println("中断了");
							}
						}
						System.out.println(Thread.currentThread().getName());
					}
				}
			}.start();
		}
		//输入是否允许释放线程闩,即是否调用countDown()方法
		Scanner sc = new Scanner(System.in);
		String flag = sc.nextLine();
		if(flag.equals("continue")){
			count.countDown();
		}else{
			System.out.println("您选择了直接退出!!!");
			System.exit(0);
		}
	}
}

输出的结果是:

Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-1
Thread-1
Thread-1
Thread-1
Thread-1
Thread-2
Thread-2
Thread-2
Thread-2
Thread-2
<span style="color:#33cc00;">continue</span>
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-1
Thread-1
Thread-1
Thread-1
Thread-1
Thread-2
Thread-2
Thread-2
Thread-2
Thread-2
从上面的结果可以看出,当j=5时,await方法导致线程休眠等待释放线程闩,当输入continue后,释放线程闩,所有处于等待状态的信号都开始执行。注意,这里线程闩的数量为1,所以调用一次countDown就减少到0了,这样所有等待的线程就都可以允许调用执行了。
再看另外一个例子。
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
	private static int COUNT = 5;
	private static CountDownLatch countLatch = new CountDownLatch(COUNT);
	public static void main(String[] args) {
		doStuff1();
	}public static void doStuff1(){
		//启动五个线程,并在每个线程末尾进行闩的减数操作
		for(int i = 0; i<COUNT; i++){
			new Thread(){
				public void run(){
					for(int j = 0; j<5; j++){
						System.out.println(Thread.currentThread().getName());
					}
					countLatch.countDown();
				}
	 	    }.start();
		}
		//调用await方法等待所有的线程结束
		try {
			countLatch.await();
			System.out.println("所有的线程已经结束");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

执行结果:
Thread-1
Thread-1
Thread-1
Thread-1
Thread-1
Thread-3
Thread-3
Thread-3
Thread-3
Thread-3
Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-2
Thread-2
Thread-2
Thread-2
Thread-2
Thread-4
Thread-4
Thread-4
Thread-4
Thread-4
所有的线程已经结束

从结果中可以看出,主线程等待所有线程执行结束后,才执行await方法后面的语句。这跟前面的例子道理是相同的。注意,这里线程闩的数量为5,由于每次线程结束时都会调用一次countDown()方法,所以数量就会减1,当5个线程都结束的时候,数量就会减为0,通知await方法就会被通知到继续执行该方法后面的代码。
需要注意的是,如果count初始的数量大于countDown方法调用的次数,会出现什么情况呢?那就是count永远也减小不到0,所以await()方法将会永远阻塞。设计时要避免这样的情况发生。可以调用await的重载版本await(int,TimeUnit.SENCONDS),这个方法指定要等待的时间,超时就不等了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值