最近在研究类似于迅雷的多线程下载,写好代码后就会有测试多线程效率这么一个环节,于是就遇见了如何统计多个线程执行时间的问题,即从第一个线程启动,到最后一个线程执行完毕所消耗的时间。我们知道,当一个主方法启动完成N个线程后,不会等到N个线程执行完毕才结束方法,所以这里该如何监听每个线程的执行完成与否的状态呢?
CountDownLatch,是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。此类的工作原理大致是:首先存在一个锁存器计数器,先指定好锁存器中盛放的线程个数,比如3个,每当执行一次countDown()方法,锁存器倒计数就会减1,直至锁存器中的数字减为0时,触发await()方法,让处于阻塞状态的主方法重新恢复非阻塞状态,从而有效的保证了每个线程执行完毕。
此类具备一个构造器和五个方法:
构造器:CountDownLatch(int count)
count-指定锁存器中盛放的线程个数
方法: await() - 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断
await(long timeout,TimeUnit unit)
- 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。timeout是等待时间,unit是时间单位。
countDown()
- 递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
getCount()
- 返回当前计数。
toString()
- 返回标识此锁存器及其状态的字符串。
不多废话,先上代码:
package downLoad;
import java.util.concurrent.CountDownLatch;
public class Test {
private static Test test;
private CountDownLatch cdl;
private Test(){
cdl = new CountDownLatch(3);
}
public CountDownLatch getCdl(){
return cdl;
}
public static Test getInstance(){
if(test == null){
test = new Test();
}
return test;
}
public static void main(String[] args) {
//初始化COuntDownLatch
Test.getInstance();
//开始时间
long start = System.currentTimeMillis();
for(int i=0;i<3;i++){
new TestThread().start();;
}
//让主线程处于阻塞状态,直到其他线程执行完毕再唤醒
try {
getInstance().getCdl().await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("耗时:"+(System.currentTimeMillis()-start)+"毫秒");
}
public static class TestThread extends Thread{
@Override
public void run() {
String str = "";
for(int i=0;i<10000;i++){
// System.out.println(i);
str += i;
}
System.out.println(Thread.currentThread().getName()+" is over...");
Test.getInstance().getCdl().countDown();
}
}
}
在Test类中,定义了全局变量CountDownLatch对象,以及一个内部线程类,通过代码我们就能够明白CountDownLatch的用法了。