您的位置:首页 > 编程语言 > Java开发

java CountDownLatch(闭锁)

2016-04-12 20:35 447 查看
CountDownLatch的和join有类似之处,但是比join强大并且灵活许多。

在实例化一个CountDownLatch时,需要设置一个初始计数,所有调用await()方法的线程都会阻塞直到计数减为零,countDown()方法每调用一次 ,计数减一直到减为零从而唤醒其他所有调用await()方法的线程。

CountDownLatch的计数功能是一次性的,即它的计数减为零时,不能再重新设置它的值。

当CountDownLatch初始化计数设置为1时,它可以作为一个开关或者门(a simple on/off latch, or gate),即所有调用await()方法的线程都必须等待一个线程调用CountDown()方法,那么就相当于一个开关,只有调用countDown()之后线程才可以通过。

当CountDownLatch初始计数置为N时,调用await()方法的线程必须等待N个线程调用完成某个事件。

和join最大的区别是等待线程是等待其他N个线程调用CountDown()方法而不是线程结束。

来看一个例子(一个货车司机和几个码头工人,首先码头工人需要等待火车司机把车开到码头才能装货,其次货车司机需要等待所有的工人将货物装上车它才能把车开走)

public class Diver {
public static void main(String[] args) throws InterruptedException{
CountDownLatch canDrive = new CountDownLatch(5);//有五个工人
CountDownLatch canLoad = new CountDownLatch(1);
//五个工人在等待
for(int i = 0; i < 5; i++){
new Thread(new Worker(canDrive,canLoad),"" + i).start();
}
Thread.sleep(400);//让工人线程先执行
System.out.println("老司机把车开来了");
canLoad.countDown();
canDrive.await();
System.out.println("老司机把车开走了");
}
}

class Worker implements Runnable{
private CountDownLatch canDrive;//开车开关
private CountDownLatch canLoad;//装货开关
public Worker (CountDownLatch canDrive, CountDownLatch canLoad){
this.canDrive = canDrive;
this.canLoad = canLoad;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + ": 在等车来啊");
canLoad.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": 我把货装好了");
canDrive.countDown();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "装完货我得抽根烟冷静一下");
}
}
result:
0: 在等车来啊
1: 在等车来啊
2: 在等车来啊
3: 在等车来啊
4: 在等车来啊
老司机把车开来了
0: 我把货装好了
1: 我把货装好了
3: 我把货装好了
4: 我把货装好了
2: 我把货装好了
老司机把车开走了
0装完货我得抽根烟冷静一下
1装完货我得抽根烟冷静一下
3装完货我得抽根烟冷静一下
2装完货我得抽根烟冷静一下
4装完货我得抽根烟冷静一下
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程 java