JUC之CountDownLatch
1.简介
countDownLatch是在java1.5被引入的,是java.util.current包下的一个类,简称JUC线程工具类(另外三个类后续介绍),使一个线程等待其他线程各自执行完毕后再执行。
2.原理
内部是通过一个计数器(抽象类AbstractQueuedSynchronizer有个int类型的state变量即计数器)来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在休眠等待的线程就可以恢复工作了。
3.源码
3.1.构造方法
CountDownLatch(int count)构造一个指定计数的CountDownLatch,count为线程的数量,一旦设置不可修改。当然有的博客说也可以大于线程的数量(暂时还没验证是否会有问题)
3.2.Sync内部类
Sync是CountDownLatch的一个内部类继承AbstractQueuedSynchronizer类简称AQS,后面的await(), countDown()都是通过这个内部类操作AQS这个类。
3.3.await()
比较常用的一个方法,调用此方法的线程进入休眠状态,除非线程被中断。直到计时器为0时,才恢复执行。
3.4.await(long timeout, TimeUnit unit)
await重载的另一个方法,与上述方法区别可以设置超时等待时间,这个方法我没用过,感觉不太常用。(后面用到的话在进行补充)
3.2.countDown()
如果计数器到达零,则释放所有等待的线程。如果当前计数大于零,则将计数-1。
3.2.getCount()
获取计时器当前的数值,就上述的那个state的值。
4.基本使用demo
4.1场景:双十一秒杀活动,这个活动可以理解为主线程,小明、张三、李四三个人分别为子线程,都准备抢购了。代码如下:
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(1);
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
public void run() {
try {
//当前线程阻塞
latch.await();
//多线程中随机数
Thread.sleep(3000+ThreadLocalRandom.current().nextInt(1000));
System.out.println("线程"+Thread.currentThread().getName() + "抢到了!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
try {
Thread.sleep(5000L);
//所有线程恢复运行
latch.countDown();
System.out.println("5s后秒杀活动开始...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
运行结果如下:
4.2场景:学校准备考试,监考老师肯定要收完所有卷子才会离开。代码如下:
public static void main(String[] args) {
int size = 5;
CountDownLatch latch = new CountDownLatch(size);
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(2000+ThreadLocalRandom.current().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getName() + "同学卷子交了!");
latch.countDown();
}
}).start();
}
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("所有人都交齐了,监考老师离开教室!");
}