摘要
本文主要介绍Java多线程并发中闭锁(Latch)的基本概念、原理、实例代码、应用场景,通过学习,可以掌握多线程并发时闭锁(Latch)的使用方法。
概念
“闭锁”就是指一个被锁住了的门将线程a挡在了门外(等待执行),只有当门打开后(其他线程执行完毕),门上的锁才会被打开,a才能够继续执行。
闭锁(Latch),目的是使多个线程在完成各自任务后,才会打开继续执行后面的任务,否则一直等待。
计数器闭锁(CountDownLatch)是一个同步工具类, 可以用来协调多个线程的执行时间,允许一个或多个线程等待某个事件的发生。
CountDownLatch有个正数的计数器,countDown(); 对计数器做减法操作,await(); 等待计数器等于0。所有await的线程都会阻塞,直到计数器为0或者等待线程中断或者超时。
例如, 可以让a线程在其他线程运行完毕后再执行。如果其他线程没有执行完毕,则a线程就会一直等待。
原理分析
CountDownLatch的实现原理:
1、CountDownLatch在创建时, 会指定一个计数器,表示等待线程的执行数量(比如,3就表示当3个线程执行完毕后,再结束闭锁,使a能够继续执行);
2、 其他每个线程在各自执行完毕时, 分别调用一次countDown())方法,用来递减计数器, 表示有一个线程已经执行完毕了;这时, 线程a可以调用await()方法, 用来等待计数器的值为0。
3、如果计数器的值大于0, 那么await()方法会一直阻塞, 直到计数器为0时,线程a才会继续执行;
4、如果线程a一直无法等到计数器为0,则会显示等待超时,当然也可以在线程a等待时,通过程序中断等待。
实例代码
在Java中, 可以使用CountDownLatch实现多线程闭锁,具体实现代码如下:
代码语言:javascript复制package com.javalearns.juc;
import java.util.concurrent.CountDownLatch;
public class JavaLearnsCountDownLatch {
public static void main(String[] args) {
//计数器为8
CountDownLatch countDownLatch = new CountDownLatch(8);
//将CountDownLatch对象传递到线程的run()方法中,当每个线程执行完毕run()后就将计数器减1
MyThread myThread = new MyThread(countDownLatch);
long start = System.currentTimeMillis();
//创建8个线程,并执行
for (int i = 0; i <8; i ) {
new Thread(myThread).start();
}
try {
//主线程(main)等待:等待的计数器为0;即当CountDownLatch中的计数器为0时,Main线程才会继续执行。
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("耗时:" (end - start));
}
}
class MyThread implements Runnable {
private CountDownLatch latch;
public MyThread(CountDownLatch latch) {
this.latch = latch;
}
@Override
public void run() {
try {
Thread.sleep(5000);
}catch (InterruptedException e){
e.printStackTrace();
}
finally {
latch.countDown();//每个子线程执行完毕后,触发一次countDown(),即计数器减1
}
}
}
应用场景
1、确保某个计算,在其需要的所有资源都准备就绪后再执行,比如:要计算某个工程材料的合价,要知道材料的单价和工程量后,才能执行材料合价计算。
2、确保某个服务,在其依赖的所有其他服务都已经启动后再启动。
3、确保某个任务,在所有参与者都准备就绪后再执行,比如:线上上课,在全班30个同学都全部上线后,老师才能开始上课。