一、CountDownLatch 部分API
1.CountDownLatch(int count).用给定的count值构造一个CountDownLatch().
2.countDown()方法. 每调用一次该方法,count的计数就会减少1。
3.await()方法。阻塞等待,直到count至0。
二、CountDownLatch的使用场景
1.模拟多个线程同时开始调用某个方法,方法调用后统计各个线程调用该方法的总耗时,这样可以模拟测试被调方法的并发效果。
2.多人跑步比赛的例子。涉及的角色有:跑步参赛的选手(类似于业务中的某个方法)、裁判员。10人参加跑步比赛一般的过程是:10名跑步参赛选手陆陆续续站在自己的跑道上等待裁判员鸣枪发布开始比赛的信号;裁判员陆续清点是否10名选手都已经站在各自的跑道上;10名参赛选手全部站在各自跑道上(这里假设要10名参赛选手全部到场后才能开始);裁判员鸣枪,比赛开始。10个参赛选手有的跑得快有的跑得慢,但最终10个人全部跑完赛程该次比赛结束。
三、用CountDownLatch模拟10人参加跑步比赛的过程。
1. 涉及到的类有Service(模拟跑步),MyThread(模拟一名参赛选手),CountDownLatchDemo(模拟整个跑步比赛场景)。
2. 各个类的详细代码。
(1)Service(模拟跑步)
package test;
public class Service {
public void testMethod() {
try {
System.out.println(Thread.currentThread().getName() + " begin timer " + System.currentTimeMillis());
Thread.sleep((long) (Math.random()*10000));//模拟每个跑步选手跑完100米所需的时间
System.out.println(Thread.currentThread().getName() + " end timer " + System.currentTimeMillis());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
(2)MyThread(模拟一名参赛选手)
package test;
import java.util.concurrent.CountDownLatch;
public class MyThread extends Thread {
private Service service;
private final CountDownLatch begin;
private final CountDownLatch end;
public MyThread(Service service, CountDownLatch begin, CountDownLatch end){
this.service = service;
this.begin = begin;
this.end = end;
}
public void run(){
try {
begin.await();//每个参赛选手都站在自己的跑道上,做好了比赛的准备,正在等裁判鸣枪开始比赛
service.testMethod();//听到鸣枪后比赛开始了
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
end.countDown();//其中的一个参赛选手已经跑完了
}
}
}
(3)CountDownLatchDemo(模拟整个跑步比赛场景)
package test;
import java.util.concurrent.CountDownLatch;
public class CountDownDemo {
public static void main(String[] args) {
try {
Service service = new Service();
CountDownLatch begin = new CountDownLatch(1);//裁判员鸣枪信号
CountDownLatch end = new CountDownLatch(10);//10名参赛选手结束信号
MyThread[] threadArray = new MyThread[10];
for(int i = 0 ; i < 10; i++){
threadArray[i] = new MyThread(service,begin,end);
threadArray[i].setName((i + 1) + " 号选手 ");
threadArray[i].start();
}
System.out.println("在等待裁判员鸣枪 " + System.currentTimeMillis());
long t1 = System.currentTimeMillis();//记录比赛的开始时间
begin.countDown();//裁判员鸣枪了
end.await();//等待10个参赛选手都跑完100米
long t2 = System.currentTimeMillis();//记录比赛的结束时间
System.out.println("所有参赛选手都完成了100米赛跑,赛跑总耗时是 " + (t2-t1));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3. 运行结果
在等待裁判员鸣枪 1521087478233
1 号选手 begin timer 1521087478233
5 号选手 begin timer 1521087478233
7 号选手 begin timer 1521087478233
3 号选手 begin timer 1521087478233
2 号选手 begin timer 1521087478233
10 号选手 begin timer 1521087478233
9 号选手 begin timer 1521087478233
8 号选手 begin timer 1521087478233
4 号选手 begin timer 1521087478233
6 号选手 begin timer 1521087478233
3 号选手 end timer 1521087478435
2 号选手 end timer 1521087480521
4 号选手 end timer 1521087480712
9 号选手 end timer 1521087481602
10 号选手 end timer 1521087482179
7 号选手 end timer 1521087482743
5 号选手 end timer 1521087483620
8 号选手 end timer 1521087485227
1 号选手 end timer 1521087486867
6 号选手 end timer 1521087488049
所有参赛选手都完成了100米赛跑,赛跑总耗时是 9816
四、CountDownLatch使用总结
1. 用来控制多个线程执行业务方法的时序。
2.使用CountDownLatch的countDown方法后count计数减少至0,在程序中CountDownLatch不能循环使用。