JUC工具类

在黑马点评项目实战中使用Redis实现全局秒杀的课程中,提到了一个名词JUC,在测试生成随机id的有效性时使用到了JUC的工具类:CountDownLatch,这里简单进行一个介绍和了解,想学习更具体的有关多线程与并发编程的内容,可以去看黑马有专门的JUC教程。

一、CountDownLatch:多线程协调工具类

​CountDownLatch​​ 是 Java 并发包(JUC)中的一个​​同步辅助类​​,主要用于协调多个线程的执行顺序,允许​​一个或多个线程等待其他线程完成操作​​后再继续执行。它的核心机制是通过一个“计数器”实现线程间的等待/通知。

核心特点:
  • ​计数器初始化​​:创建时指定一个初始计数值(count),表示需要等待的线程数量或任务阶段数。
  • ​countDown()​​:每个线程完成任务后调用,将计数器减 1(不可逆,减到 0 后无法恢复)。
  • ​await()​​:等待线程调用,阻塞直到计数器变为 0(或被中断、超时)。
典型场景:
  • 主线程等待所有子线程完成初始化后,再开始执行后续逻辑(例如:多线程加载资源,主线程等待所有资源加载完毕)。
  • 多阶段任务中,前一阶段的所有线程完成后,才能进入下一阶段(例如:多线程计算子任务,汇总结果前等待所有子任务完成)。
示例代码:
import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        // 初始化计数器为 3(等待 3 个子线程完成)
        CountDownLatch latch = new CountDownLatch(3);

        // 启动 3 个子线程
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " 执行任务...");
                    Thread.sleep(1000); // 模拟任务耗时
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    latch.countDown(); // 任务完成后计数器减 1
                }
            }).start();
        }

        // 主线程等待计数器归零
        latch.await();
        System.out.println("所有子线程任务完成,主线程继续执行...");
    }
}
注意:
  • 计数器​​只能使用一次​​(减到 0 后无法重置),若需要重复等待,可使用 CyclicBarrier(循环屏障)。

二、JUC 是什么?

​JUC​​ 是 java.util.concurrent 包的缩写(全称:Java Utility Classes for Concurrency),是 Java 平台提供的​​并发编程工具包​​,始于 JDK 1.5(由 Doug Lea 设计)。它封装了多线程编程中最核心的工具类,解决了早期 Java 多线程编程(如 synchronized 关键字)的性能和灵活性问题。

JUC 覆盖了多线程编程的几乎所有场景,包括:
线程池、锁(细粒度锁、读写锁)、原子操作、并发集合、同步工具类(等待/通知机制)、异步编程等。

三、JUC 常用工具类分类

JUC 工具类可按功能分为以下几大类,以下是最核心的工具类及其用途:


1. ​​同步工具类(线程协调)​

用于控制多个线程的执行顺序或协作,解决“等待-通知”问题。

  • ​CountDownLatch​​:前面已介绍,一次性计数器,等待多个任务完成。
  • ​CyclicBarrier​​:循环屏障,允许多个线程在某个屏障点等待,直到所有线程到达后一起继续执行(可重复使用)。
    示例:多线程计算分片数据,全部完成后合并结果。
  • ​Semaphore​​:信号量,控制同时访问某一资源的线程数量(限流)。
    示例:数据库连接池限制同时连接数。
  • ​Exchanger​​:交换器,两个线程在屏障点交换数据。
    示例:生产者-消费者模型中交换生产的数据和消费的位置。

2. ​​锁(Lock)​

提供比 synchronized 更灵活的锁机制(可中断、超时、公平锁等)。

  • ​ReentrantLock​​:可重入互斥锁,支持公平/非公平模式(默认非公平)。
    特性:可通过 tryLock() 尝试获取锁,避免死锁;支持条件变量(Condition)实现精准唤醒。
  • ​ReadWriteLock​​:读写锁接口,分离读锁(共享)和写锁(独占),适合读多写少场景。
    实现类:ReentrantReadWriteLock
  • ​StampedLock​​:更高效的读写锁(JDK 8 引入),支持“乐观读”(无锁读取),进一步优化读多写少场景。
  • ​LockSupport​​:底层线程阻塞/唤醒工具(park()/unpark()),用于实现自定义锁或线程协作。

3. ​​原子类(Atomic)​

基于 CAS(Compare-And-Swap,无锁算法)实现的无锁线程安全操作,避免传统锁的开销。

  • ​基础类型原子类​​:AtomicIntegerAtomicLongAtomicBoolean(通过 CAS 保证操作的原子性)。
  • ​引用类型原子类​​:AtomicReference(原子更新对象引用)、AtomicMarkableReference(带标记的引用原子更新)。
  • ​数组原子类​​:AtomicIntegerArrayAtomicLongArray(原子更新数组元素)。
  • ​字段原子类​​:AtomicIntegerFieldUpdater(原子更新对象的某个 int 字段)。

示例

AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet(); // 原子自增(等价于 i++,但线程安全)

4. ​​并发集合(Concurrent Collections)​

线程安全的集合类,优化了多线程环境下的读写性能(相比 Collections.synchronizedXXX() 更高效)。

  • ​List​​:CopyOnWriteArrayList(写时复制,适合读多写少场景,迭代时不抛出 ConcurrentModificationException)。
  • ​Set​​:CopyOnWriteArraySet(基于 CopyOnWriteArrayList 实现)、ConcurrentSkipListSet(跳表实现,有序且线程安全)。
  • ​Map​​:ConcurrentHashMap(分段锁/JDK 8 后CAS+红黑树,高并发下性能优于 Hashtable)、ConcurrentSkipListMap(有序且线程安全)。
  • ​Queue​​:ConcurrentLinkedQueue(无界非阻塞队列)、BlockingQueue 接口(阻塞队列,支持生产者-消费者模型,如 ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueue)。

5. ​​线程池(ThreadPool)​

管理线程的生命周期,避免频繁创建/销毁线程的开销,是高性能多线程编程的核心。

  • ​核心接口/类​​:
    • Executor:线程池顶层接口(execute(Runnable))。
    • ExecutorService:扩展接口(支持 submit(Callable)shutdown() 等)。
    • ThreadPoolExecutor:核心实现类(可通过构造函数自定义线程数、拒绝策略等)。
    • ScheduledExecutorService:定时任务线程池(替代 Timer,支持延迟/周期性任务)。
  • ​工具类​​:Executors(工厂类,提供快速创建线程池的方法,如 newFixedThreadPoolnewCachedThreadPoolnewSingleThreadExecutor)。
    注意:JDK 8 后推荐直接使用 ThreadPoolExecutor 构造函数自定义参数,避免 Executors 工厂方法可能导致的OOM(如无界队列)。

6. ​​异步编程(Future & CompletableFuture)​

解决多线程任务的异步执行与结果获取问题。

  • ​Callable & Future​​:Callable 是可返回结果的任务(区别于 Runnable),Future 用于获取异步任务的结果(get() 阻塞等待)。
    示例
    ExecutorService executor = Executors.newSingleThreadExecutor();
    Future future = executor.submit(() -> {
        Thread.sleep(1000);
        return 42;
    });
    int result = future.get(); // 阻塞直到任务完成
  • ​CompletableFuture​​(JDK 8 引入):更强大的异步编程工具,支持链式调用、组合多个异步任务(thenApplythenComposeallOfanyOf 等),解决回调地狱问题。

7. ​​其他工具类​
  • ​Phaser​​:更灵活的分阶段同步工具(替代 CyclicBarrier),支持动态调整参与线程数。
  • ​FutureTask​​:RunnableFuture 的实现类,结合了 RunnableFuture,可作为任务提交给线程池。
  • ​ThreadLocalRandom​​:JDK 7 引入的线程本地随机数生成器(替代 Math.random(),高并发下性能更好)。

总结

CountDownLatch 是 JUC 中用于线程协调的同步工具类,而 JUC 是 Java 并发编程的核心工具包,覆盖了锁、原子操作、并发集合、线程池、异步编程等几乎所有多线程场景。掌握这些工具类能显著提升多线程程序的性能和可靠性。

你可能感兴趣的:(JUC工具类)