先讲一个应用场景:就是计算10个线程跑完需要多久时间!
也许有人这样写:
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
for(int i=0;i<100;i++){
new Thread(new Runnable() {
public void run() {
for(int j=0;j<1000000000;j++){
//
}
}
}){}.start();
}
long end = System.currentTimeMillis();
System.out.println("总耗时:"+(end-start));
}
}
你打印结果出来发现总是1秒或者2秒,怎么时间花的这么短呢?答案是这种做法肯定错了,因为这是在mian线程中的,而其他线程都还在执行,也就是说要等线程结束后再计算end值才是正确的,分析如图:
java中为我们提供了线程同步计算类,就是CountDownLatch
解释:一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待
CountDownLatch
是一个通用同步工具,它有很多用途。将计数 1 初始化的CountDownLatch
用作一个简单的开/关锁存器,或入口:在通过调用countDown()
的线程打开入口前,所有调用await
的线程都一直在入口处等待。用N 初始化的 CountDownLatch
可以使一个线程在N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。
CountDownLatch
的一个有用特性是,它不要求调用 countDown
方法的线程等到计数到达零时才继续,而在所有线程都能通过之前,它只是阻止任何线程继续通过一个await
它的几个方法:
构造方法:
CountDownLatch(int count)
构造一个用给定计数初始化的 CountDownLatch。
普通方法:
void await()
使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
boolean await(long timeout, TimeUnit unit)
使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间
void countDown()
递减锁存器的计数,如果计数到达零,则释放所有等待的线程
上面几个方法等下通过一个例子都会明白
long getCount()
返回当前计数
实例代码:
import java.util.concurrent.CountDownLatch;
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
int threadNum = 1000;
final CountDownLatch countDownLatch = new CountDownLatch(threadNum);
long start = System.currentTimeMillis();
for(int i=0;i<threadNum;i++){
new Thread(new Runnable() {
public void run() {
for(int j=0;j<1000000000;j++){
//
}
countDownLatch.countDown();
}
}){}.start();
}
countDownLatch.await();//一直在阻塞 等待线程执行完后
System.out.println("-----------打log测试-----------");//这个打log可以看的出来是等线程执行完后再执行下面的代码
long end = System.currentTimeMillis();
System.out.println("总耗时:"+(end-start));
}
}