一、CountDownLatch工具类介绍
CountDownLatch类是Java并发工具常用的四大工具之一,CountDownLatch允许一个或者多个线程等待其他线程完成工作。假设我们有这样的一个需求,我们需要解析一个Excel里多个sheet的据,这个时候我们考虑使用多 线程同时进行工作,每个线程解析一个sheet里的数据,等到所有的sheet都解析完之后,程序需要提示解析完成将数据返回。在这个需求中,要实现主线程等待所有线程完成sheet的解析操作。在这种情况之下我们就可以考虑使用CountDownLatch工具类。
1 2 import java.util.concurrent.CountDownLatch; 3 4 public class CountDownLatchUserCase { 5 6 private static CountDownLatch countDownLatch = new CountDownLatch(5); 7 8 public static void main(String[] args) throws Exception{ 9 //主线程开始读取Excel文档 10 new Excel().start(); 11 long count = countDownLatch.getCount(); 12 for(int i = 0;i < count;i++){ 13 new Sheet().start(); 14 } 15 } 16 17 static class Excel extends Thread{ 18 19 @Override 20 public void run(){ 21 try { 22 System.out.println("开始读取Excel文档,共有"+countDownLatch.getCount()+"个工人同时工作"); 23 countDownLatch.await(); 24 }catch (Exception e){ 25 e.printStackTrace(); 26 } 27 System.out.println("所有Excel文档工作读取完毕"); 28 } 29 } 30 31 static class Sheet extends Thread{ 32 33 @Override 34 public void run(){ 35 System.out.println(Thread.currentThread().getName() + ",完成sheet读取工作...."); 36 //完成其中一个sheet的工作 count - 1 37 countDownLatch.countDown(); 38 } 39 40 } 41 42 } 43
1 开始读取Excel文档,共有5个工人同时工作 2 Thread-4,完成sheet读取工作.... 3 Thread-2,完成sheet读取工作.... 4 Thread-3,完成sheet读取工作.... 5 Thread-1,完成sheet读取工作.... 6 Thread-5,完成sheet读取工作.... 7 所有Excel文档工作读取完毕
CountDownLatch是通过一个计数器来实现的,当我们在new 一个CountDownLatch对象的时候需要带入该计数器值,该值就表示了线程的数量。每当一个线程完成自己的任务后,计数器的值就会减1。当计数器的值变为0时,就表示所有的线程均已经完成了任务,然后就可以恢复等待的线程继续执行了。
CountDownLatch类只提供了一个构造器:
1 public CountDownLatch(int count) { }; //参数count为计数值
CountDownLatch类中提供了3个最重要的方法:
1 public void await() throws InterruptedException { }; //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行 2 public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行 3 public void countDown() { }; //将count值减1
二、CountDownLatch原理分析
CountDownLatch内部通过共享锁实现。CountDownLatch的构造函数接收一个int类型的参数作为计数器,这个计数器的值也可以理解为该共享锁可以获取的总次数。如果你想等待N个点完 成,这里就传入N。当我们调用CountDownLatch的countDown方法时,N就会减1,当线程调用await方法的时候,程序首先判断count的值是否为0,如果不会0的话则会阻塞当前线程一直等待直到为0为止。
注意:CountDownLatch不可能重新初始化或者修改CountDownLatch对象的内部计数 器的值。
CountDownLatch不能回滚重置。