CountDownLatch简单使用
CountDownLatch是一个倒计时锁存器,用来实现线程之间的同步操作
1.创建一个runable实现类
public class Worker implements Runnable {
private List<String> outputScraper;
private CountDownLatch countDownLatch;
public Worker(List<String> outputScraper, CountDownLatch countDownLatch) {
this.outputScraper = outputScraper;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
doSomeWork();
outputScraper.add("countDown");
countDownLatch.countDown();
}
}
2.创建测试类
@Test
public void test() throws InterruptedException {
List<String> outputScraper = Collections.synchronizedList(new ArrayList<>());
CountDownLatch countDownLatch = new CountDownLatch(5);
List<Thread> workers = Stream
.generate(() -> new Thread(new Worker(outputScraper, countDownLatch)))
.limit(5)
.collect(toList());
workers.forEach(Thread::start);
countDownLatch.await();
outputScraper.add("latchReleased");
assertThat(outputScraper).containsExactly("countDown","countDown","countDown","countDown","countDown","latchReleased");
}
此方法中创建了一个线程安全List和一个倒计时锁存器,锁存计数值为5,再创建5个线程执行Worker任务,传入的参数是同一个List和CountDownLatch,然后启动全部线程,在任务的run方法的最后调用countDownLatch.countDown()使计数器-1,在主线程中调用countDownLatch.await()等待计数器为0,然后再继续执行后面代码,保证了outputScraper.add(“latchReleased”)是在所有的outputScraper.add(“countDown”)之后才添加的。
异常处理
如果任务中途出现异常导致计数器锁存器不能正常-1,导致主线程一直等不到计数器为0,解决办法:
boolean completed = countDownLatch.await(3L, TimeUnit.SECONDS);
设置超时时间,如果规定时间内等待不到计数器清零则返回false。