在工作用,有些业务实现需要主线程等待子线程全部运行完之后才继续向下运行,在不使用CountDownLatch的情况下,我们的做法通常是这样:
public class CountDownLatchTest {
/**
* 不使用CountDownLatch
*/
private static int threadCount = 10;
private static int hasRunCount = 0;
public static void main(String[] args) {
for(int i = 0; i < 10; i++){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"开始执行!");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName()+"执行结束!");
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
synchronized (CountDownLatchTest.class) {
hasRunCount++;
}
}
}
});
thread.start();
}
while(threadCount>hasRunCount){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("所有线程执行完毕!");
}
}
通过两个计数变量来判断和控制是否全部线程都已经执行完毕,是否继续向下执行。
下面来看看使用CountDownLatch怎么实现:
import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest {
/**
* 使用CountDownLatch
*/
public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(10);
for(int i=0;i<10;i++){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try{
System.out.println(Thread.currentThread().getName()+"开始执行");
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName()+"执行结束");
}catch(Exception e){
e.printStackTrace();
}finally{
latch.countDown();
}
}
});
thread.start();
}
try {
latch.await();
System.out.println("所有线程执行完毕!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
CountDownLatch是一个同步功能的辅助类。使用效果是给定一个计数器,当使用这个CountDownLatch类的线程判断计数器不为0时,则呈wait状态,如果为0则继续运行。实现等待与继续运行的效果分别需要使用await()和countDown()方法来进行,调用await()方法时判断计数是否为0,如果不为0则呈等待状态。其他线程可以调用countDown()方法将计数减1,当计数器减到为0时,呈等待的线程继续运行。而方法getCount()就是获得当前的计数个数。
需要说明的是,CountDownLatch的计数是减法操作,且计数无法被重置。
方法await(long timeout, TimeUnit unit)的作用使线程在指定的最大时间单位内进入WAITING状态,如果超过这个时间则自动唤醒,程序继续向下运行。参数timeout是等待的时间,而unit参数是时间的单位。
方法getCount()获取当前计数的值。
欢迎入群交流