Python 官方文档:入门教程 => 点击学习
目录CountDownLatch原理解析1. demo展示2. 原理解析Java CountDownLatch学习总结来源包业务书写示例一般代码示例CountDownLatch原理解
代码逻辑展示了主线程中创建2个子线程分别去执行任务,主线程等2个子线程执行完毕后,再接着执行下面的代码;
常用场景:
分别计算,汇总结果。如,多个线程分别解析excel中的sheet,等待全部解析完毕后汇总结果;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class CountDownLatchDemo {
//定义一个倒计时闩锁
static CountDownLatch c = new CountDownLatch(2);
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
try {
TimeUnit.MICROSECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是线程1");
//释放一个
c.countDown();
}).start();
new Thread(() -> {
try {
TimeUnit.MICROSECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是线程2");
//释放一个
c.countDown();
}).start();
System.out.println("我是主线程,我要等那两个线程执行完毕...");
//等待倒计时为0
c.await();
System.out.println("我是主线程,那两个线程都执行完了");
}
}
输出:
我是主线程,我要等那两个线程执行完毕...
我是线程2
我是线程1
我是主线程,那两个线程都执行完了
1.先看构造函数new CountDownLatch(2)做了什么?
这是初始化了AQS子类,并将AQS的状态state设置为传入的2;
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
2.看c.countDown()做了什么?
它释放了一个共享锁状态,也就是state减1;
public void countDown() {
sync.releaseShared(1);
}
3.再看c.await()做了什么?
await方法是CounDownLatch中定义的,它调用了其内部类Sync(也是AQS的子类)的获取共享锁的方法acquireSharedInterruptibly;
acquireSharedInterruptibly方法中调用了CountDownLatch内部类Sync中实现的获取共享锁的方法tryAcquireShared,返回值不小0就算获取到了锁,await方法就能返回了,如果返回值小于0将会进入阻塞等待;
CountDownLatch内部类Sync中tryAcquireShared的实现很简单,只要state=0就返回1,否则返回-1;上面说了返回一个不小于0的数字,c.await()就相当于获取到了锁,就可以返回了,主线程就可以继续执行了。
通过上面分析,每次c.countDown(),就会将state减1,state=0的时候主线程恢复执行;
同为 java.util.concurrent 下的,即也是并发多线程相关下的类,直译 “倒计时锁存器”,一般用于多线程场景,单一的线程也可以,用于等待多个任务完成后再执行其他操作;
提供方法
await()
如果当前线程:
简单说就是当使用了这个方法后当前这一个线程将进入等待状态,直到计数器被减到0或者当前线程被中断,计数器被减到0后,所有等待的线程将被唤醒继续向下执行
await(long timeout, TimeUnit unit)
同上,但是指定了等待的超时时间,即线程除了上方两种被唤醒的情况下,等待到超时时间后也会被唤醒
countDown()
:当前计数器减一,如果如果减到 0 则唤醒所有等待在这个 CountDownLatch 上的线程。getCount()
:获取当前计数的数值即将需要一会儿处理的业务 list 设置为计数器的大小,
然后对里面的业务数据执行异步操作,处理业务过程中不论是否有异常都需要对计数器减一,最终使用 await 等待所有任务执行完成,执行完成后,将进入后续处理
final CountDownLatch latch = new CountDownLatch(lists.size());
for (List<JSONObject> item: lists) {
executor.submit(new Runnable() {
@Override
public void run() {
// ....... 业务处理
} catch (Exception e) {
// 异常处理
} finally {
latch.countDown();
}
}
});
}
try {
latch.await();
} catch (InterruptedException e) {
log.error("线程被中断", e);
}
// lists 处理完成后的其他业务操作
public static void main(String[] args) throws InterruptedException {
final CountDownLatch downLatch = new CountDownLatch(3);
Await wait111 = new Await("wait111", downLatch);
Await wait222 = new Await("wait222", downLatch);
CountDownStart countDownStart = new CountDownStart(downLatch);
wait111.start();
wait222.start();
Thread.sleep(1000);
countDownStart.run();
}
class Await extends Thread{
private CountDownLatch countDownLatch;
private String name;
public Await(String name, CountDownLatch countDownLatch){
this.name = name;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println(name + " start.....");
System.out.println(name + " run.....");
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + " continue.....run");
}
}
class CountDownStart extends Thread{
private CountDownLatch countDownLatch;
public CountDownStart(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
countDownLatch.countDown();
countDownLatch.countDown();
countDownLatch.countDown();
System.out.println("start countDown");
}
}
运行结果:
wait222 start.....
wait222 run.....
wait111 start.....
wait111 run.....
start countDown
wait111 continue.....run
wait222 continue.....run
但是当我把线程等待去除后:
public static void main(String[] args) throws InterruptedException {
final CountDownLatch downLatch = new CountDownLatch(3);
Await wait111 = new Await("wait111", downLatch);
Await wait222 = new Await("wait222", downLatch);
CountDownStart countDownStart = new CountDownStart(downLatch);
wait111.start();
wait222.start();
// Thread.sleep(1000);
countDownStart.run();
}
结果:
start countDown
wait111 start.....
wait111 run.....
wait111 continue.....run
wait222 start.....
wait222 run.....
wait222 continue.....run
另外两个线程线程并没有开始就执行,可能被抢占了,也可能调度优先度不同,实际使用时还是需要多多实验
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
--结束END--
本文标题: Java之CountDownLatch原理全面解析
本文链接: https://www.lsjlt.com/news/170319.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0