JUC系列04-CountDownLatch闭锁

1 为什么要使用CountDownLatch

先通过以下例子了解CountDownLatch到作用

package com.mafgwo.juc.testvolatile;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * CountDownLatch使用例子
 */
public class TestCountDownLatch {

    public static void main(String[] args) {
        // 开10个线程打印线程名
        CountDownLatch countDownLatch = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                // 睡眠随机500ms内
                try {
                    Thread.sleep(new Random().nextInt(500));
                    System.out.println(Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }).start();
        }
        try {
            countDownLatch.await(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 打印所有线程已处理完
        System.out.println("所有线程已完成");
    }

}

其他方式实现线程等待如下

package com.mafgwo.juc.testvolatile;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * 等待线程执行完到其他例子
 */
public class TestWaitThread {

    public static void main(String[] args) {
        List threads = new ArrayList<>();
        // 开10个线程打印线程名
        for (int i = 0; i < 10; i++) {
            Thread t = new Thread(() -> {
                // 睡眠随机500ms内
                try {
                    Thread.sleep(new Random().nextInt(500));
                    System.out.println(Thread.currentThread().getName());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            threads.add(t);
            t.start();
        }
        for (Thread thread : threads) {
            try {
                thread.join(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 打印所有线程已处理完
        System.out.println("所有线程已完成");
    }

}

使用分析

两者的共同点:都能做到等待全部线程执行完再执行主线程。
两者的区别:CountDownLatch是使用计数方式,await阻塞主线程,当计数为0则继续执行。Thread.join则会不断检查线程是否存在,存活则调用wait方法阻塞线程,等待线程结束时的notifyAll。
总结:CountDownLatch主要是用于多线程时需要完成某些线程,再继续往下执行的场景,不需要等待线程关闭,便于在线程池中使用。
注意事项:第一,CountDownLatch.countDown()方法要放在finally中,避免程序异常未执行减1操作导致不必要的阻塞;第二,CountDownLatch.await方法要设置超时时间,避免某些异常场景下出现死锁。

来源:码蜂窝-JUC系列04-CountDownLatch闭锁

你可能感兴趣的:(JUC系列04-CountDownLatch闭锁)