一、CountDownLatch的API
- 构造方法摘要
构造方法
Constructor and Description |
CountDownLatch(int count)
构造一个以给定计数 CountDownLatch CountDownLatch。 |
可以看到 CountDownLatch 类有两个最重要的方法
counttDown() 让计数值-1
await() 阻塞线程,直到计数值为0才唤醒
计数值最小为0
通过一个简单的例子可以验证上面的观点,不使用线程即可
测试1
- public static void main(String args[]) throws InterruptedException {
- final CountDownLatch latch = new CountDownLatch(5);
- System.out.println("开始你的表演!");
- for(int i=0;i<3;i++) {
- latch.countDown();
- System.out.println("latch.getCount:"+latch.getCount());
- }
- latch.await();
- System.out.println("再见吧,大海!");
- }
运行结果如下
可见,当计数值为2的时候,遇到了 await(),此后将会一直处于等待状态(看左侧的红色按钮,表示程序还在等待)
测试2
- public static void main(String args[]) throws InterruptedException {
- final CountDownLatch latch = new CountDownLatch(5);
- System.out.println("开始你的表演!");
- for(int i=0;i<8;i++) {
- latch.countDown();
- System.out.println("latch.getCount:"+latch.getCount());
- }
- latch.await();
- System.out.println("再见吧,大海!");
- }
还是上面的代码,我们把 3 改成一个更大点的数,比如8
运行结果如下
结果说明,当计数值为0时,await()才会继续执行,而不会等待
同时,也发现计数值最小值为 0
二、求多线程的运行时间
CountDownLatch 允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。
这里我们可以实现一个功能,就是 “统计多线程的执行时间”,因为我们需要判断多线程是什么时候 start的,什么时候 end 的。而正好 CountDownLatch 类可以帮助我们知道什么时候结束。
让我们一步步实现它!
1、如何计算某段代码的运行时间
- public static void main(String args[]) {
- long startTime = System.currentTimeMillis();
- for(int i=0;i<1000;i++) {
- System.out.println(i);
- }
- long endTime = System.currentTimeMillis();
- System.out.println((endTime-startTime)+"ms");
- }
通过 System.currentTimeMillis() 方法获得当前系统时间(单位ms)
下面我们来求多线程的执行时间
2、失败的例子
- public static void main(String args[]) {
- System.out.println("主线程开始");
- long startTime = System.currentTimeMillis();
- for(int i=0;i<5;i++) {
- new Thread() {
- @Override
- public void run() {
- System.out.println(currentThread().getName()+"开始执行..");
- try {
- sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(currentThread().getName()+"结束执行..");
- }
- }.start();
- }
- long endTime = System.currentTimeMillis();
- System.out.println("多线程运行时间:"+(endTime-startTime)+"ms");
- System.out.println("主线程结束");
- }
运行结果如下
很显然,这是一个失败的答案。因为我们知道多线程(包括main线程)是抢占CPU执行资源的,所以一旦几个线程处于就绪状态的话,都有机会抢到执行的机会。所以,我们的两处求系统时间的地方都是我们不希望的时间。
也就是说,我们希望结果应该是这样的,
“主线程开始”-->5个子线程执行-->“主线程结束”。
3、成功的例子
- public static void main(String args[]) throws InterruptedException {
- CountDownLatch latch = new CountDownLatch(5);
- System.out.println("主线程开始");
- long startTime = System.currentTimeMillis();
- for(int i=0;i<5;i++) {
- new Thread() {
- @Override
- public void run() {
- System.out.println(currentThread().getName()+"开始执行..");
- try {
- sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(currentThread().getName()+"结束执行..");
- latch.countDown();
- }
- }.start();
- }
- latch.await();
- long endTime = System.currentTimeMillis();
- System.out.println("多线程运行时间:"+(endTime-startTime)+"ms");
- System.out.println("主线程结束");
- }
运行结果如下
这次是结果是我们想要的。
同时,我们也看到了,5个线程,每个线程需要执行 1s (停止 1s),最终 5 个线程全部执行,只需要1s多点,而不是 5s,这就是多线程的作用。
目前评论:1