java|多线程编程中如何确保子线程执行完毕后主线程再执行-CountDownLatch

定义 【java|多线程编程中如何确保子线程执行完毕后主线程再执行-CountDownLatch】ountDownLatch是在java1.5被引入,存在于java.util.cucurrent包下,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。
countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行,它是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
线性执行的案例 在多线程开发中,主线程数据通过子线程处理后返回的结果往往并不是我们想要的。如下面一个例子,我们的期望结果是300000,但是在主线程输出后并不是我们想要的:

public static AtomicInteger num = new AtomicInteger(0); public static void main(String []args) throws InterruptedException { //开启30个线程进行累加操作 for(int i=0; i<30; i++){ new Thread(){ public void run(){ for(int j=0; j<10000; j++){ num.incrementAndGet(); //原子性的num++,通过循环CAS方式 } } }.start(); } System.out.println(num); }

上面的这个例子中,num操作是原子的,线程安全的,输出的结果并不是我们想要的,是应为主线程输出时子线程还有没有结束。以下面的的代码来验证我们的想法:
public static AtomicInteger num = new AtomicInteger(0); public static void main(String []args) throws InterruptedException { //开启30个线程进行累加操作 for(int i=0; i<30; i++){ new Thread(){ public void run(){ for(int j=0; j<10000; j++){ num.incrementAndGet(); //原子性的num++,通过循环CAS方式 } } }.start(); } //等待计算线程执行完 TimeUnit.MILLISECONDS.sleep(1000); System.out.println(num); }

此时我们输出的结果就是300000了;这是我们在开发中已经预估到子线程的算法不会超过1000毫秒,如果在开发中不能确保估算的时间准确,或者估算的时间较长造成资源浪费怎么办?使用CountDownLatch即可解决这个问题。
java|多线程编程中如何确保子线程执行完毕后主线程再执行-CountDownLatch
文章图片

上图来自JDK8的API接口文档,主要有1个构造方法5个方法。
如何改造上面的代码?
public static AtomicInteger num = new AtomicInteger(0); //使用CountDownLatch来等待计算线程执行完 static CountDownLatch countDownLatch = new CountDownLatch(30); public static void main(String []args) throws InterruptedException { //开启30个线程进行累加操作 for(int i=0; i<30; i++){ new Thread(){ public void run(){ for(int j=0; j<10000; j++){ num.incrementAndGet(); //原子性的num++,通过循环CAS方式 } countDownLatch.countDown(); } }.start(); System.out.println("剩余数量"+countDownLatch.getCount()); } //等待计算线程执行完 countDownLatch.await(); System.out.println(num); }

    推荐阅读