并发编程CountDownLatch的使用以及应用场景

时间:2022-08-20 15:19:20

CountDownLatch 是一个线程辅助类,主要用到下面两个方法:

1.首先通过构造函数先初始化线程数量

     CountDownLatch countDown = new CountDownLatch(10);

2.每个线程执行完需要调用countDown()方法, 这个方法每次调用会使CountDownLatch 中的count数减去1,可以这么理解,其实count是存在CountDownLatch 中的Sync的一个父类,AbstractQueuedSynchronizer,这点其实不需要去管.


3.开启每个线程后面调用await()方法,这个方法会在CountDownLatch的线程数量还是>1的时候一直阻塞,一直到所有线程执行完之后放开.


CountDownLatch的使用场景

  假设你的所有线程在处理批量数据,要等你所有数据处理完之后才能执行后面的逻辑,这是其中一个场景,其他的可以自己想象. 反正我遇到的这种场景.


别的不多说先上一波代码加注释

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class Testssss {

public void doRun(){
//假设这个shards有十个记录, 我需要对没一个记录启用一个线程 去处理数据
List<String> shards = new ArrayList<String>(10);
//CountDownLatch要初始化线程数量, 初始化后CountDownLatch是没有提供修改的机制
CountDownLatch countDown = new CountDownLatch(shards.size());
try {
for(String shard : shards){
//这里去处理数据
new TestTheread(countDown, shard).start();
}
//调用这个方法 会在上面所有线程执行完之前进入阻塞状态
//...........假设你要等处理完数据之后再去做后面的业务,那就用的上await()了
countDown.await();
} catch (InterruptedException e) {
//log....
}
//等待上面所有线程执行完数据之后, 再处理后面的业务........
}

private class TestTheread extends Thread{

private CountDownLatch countDown;
private String shard;

public TestTheread(CountDownLatch countDown, String shard){
this.countDown = countDown;
this.shard = shard;
}

@Override
public void run() {
try {
//执行业务代码 processor(shard);.......
} catch (Throwable e) {
//log.....
} finally{
//每调用一次 countDown 中线程数量-1 一直到0为止
countDown.countDown();
}
}

}
}