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;}@Overridepublic 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。