在1些利用场合中,某段程序需要等待某个条件到达要求后才能履行,或等待1定长的时间后此行,从jdk1.5开始就能够使用CountDownLatch实现,
CountDownLatch类是1个同步倒数计数器,构造时传入int参数,该参数就是计数器的初始值,每调用1次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()后面的代码,将会被阻塞,直到调用1次cdOrder.countDown()后才向下履行;cdAnswer.await()后面代码阻塞,调用3次cdAnswer.countDown()向下履行。
所以上面履行结果:
线程pool⑴-thread⑴正准备接受命令
线程pool⑴-thread⑶正准备接受命令
线程pool⑴-thread⑵正准备接受命令
线程main行将发布命令
线程main已发送命令,正在等待结果
线程pool⑴-thread⑴已接受命令
线程pool⑴-thread⑵已接受命令
线程pool⑴-thread⑶已接受命令
线程pool⑴-thread⑵回应命令处理结果
线程pool⑴-thread⑶回应命令处理结果
线程pool⑴-thread⑴回应命令处理结果
线程main已收到所有响应结果
await(long timeout, TimeUnit unit),是等待1定时间,然后履行,不管计数器是不是到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("开车,鞋儿破 帽儿破 身上的袈裟破 你笑我 他笑我 1把扇儿破");
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;
}
}
}
‘