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();
}
}
}
}