Java的JUC并发库及其应用场景

Java 的 JUC(java.util.concurrent) 包是 Java 并发编程的核心工具集,提供了高性能、线程安全的并发类。以下是主要 JUC 类及其应用场景的详细分类解析:


一、锁与同步工具

1. ReentrantLock

  • 特点:可重入、支持公平/非公平锁、可中断、超时尝试。
  • 应用场景
    • 替代 synchronized 实现更灵活的锁控制。
    • 需要尝试获取锁或可中断锁的场景(如死锁恢复)。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    ReentrantLock lock = new ReentrantLock();
    lock.lock();
    try {
    // 临界区代码
    } finally {
    lock.unlock();
    }

2. ReentrantReadWriteLock

  • 特点:读写分离,读锁共享,写锁独占。
  • 应用场景
    • 读多写少的场景(如缓存系统)。
  • 示例
    1
    2
    3
    ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    rwLock.readLock().lock(); // 读锁
    rwLock.writeLock().lock(); // 写锁

3. StampedLock(JDK 8+)

  • 特点:乐观读锁、写锁可降级为读锁。
  • 应用场景
    • 极高并发读写场景(比 ReentrantReadWriteLock 性能更高)。
  • 示例
    1
    2
    3
    4
    5
    StampedLock lock = new StampedLock();
    long stamp = lock.tryOptimisticRead(); // 乐观读
    if (!lock.validate(stamp)) {
    stamp = lock.readLock(); // 退化为悲观读
    }

二、并发容器

1. ConcurrentHashMap

  • 特点:分段锁(JDK 7)或 CAS + synchronized(JDK 8+),高并发读写。
  • 应用场景
    • 高并发键值存储(如缓存、计数器)。
  • 示例
    1
    2
    ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
    map.computeIfAbsent("key", k -> 1); // 原子操作

2. CopyOnWriteArrayList

  • 特点:写时复制,读操作无锁。
  • 应用场景
    • 读多写少的列表(如监听器列表)。
  • 示例
    1
    2
    CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
    list.add("item"); // 写操作复制整个数组

3. BlockingQueue 接口

  • 实现类
    • ArrayBlockingQueue:固定大小数组队列。
    • LinkedBlockingQueue:可选边界链表队列。
    • PriorityBlockingQueue:优先级阻塞队列。
  • 应用场景
    • 生产者-消费者模型(如线程池任务队列)。
  • 示例
    1
    2
    3
    BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
    queue.put("item"); // 阻塞插入
    String item = queue.take(); // 阻塞取出

三、线程协作工具

1. CountDownLatch

  • 特点:一次性屏障,等待多个任务完成。
  • 应用场景
    • 主线程等待所有子线程初始化完成。
  • 示例
    1
    2
    3
    4
    5
    CountDownLatch latch = new CountDownLatch(3);
    // 子线程
    latch.countDown();
    // 主线程
    latch.await();

2. CyclicBarrier

  • 特点:可重复使用的同步屏障。
  • 应用场景
    • 多阶段任务同步(如并行计算分阶段汇总)。
  • 示例
    1
    2
    CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All threads reached barrier"));
    barrier.await(); // 线程阻塞直到所有线程到达

3. Semaphore

  • 特点:控制并发访问资源的线程数。
  • 应用场景
    • 限流(如数据库连接池)。
  • 示例
    1
    2
    3
    Semaphore semaphore = new Semaphore(5); // 允许5个线程并发
    semaphore.acquire(); // 获取许可
    semaphore.release(); // 释放许可

4. Phaser(JDK 7+)

  • 特点:动态调整的同步屏障,支持多阶段。
  • 应用场景
    • 复杂分阶段任务(如游戏多关卡加载)。
  • 示例
    1
    2
    Phaser phaser = new Phaser(3); // 注册3个线程
    phaser.arriveAndAwaitAdvance(); // 等待所有线程完成当前阶段

四、线程池与异步任务

1. ThreadPoolExecutor

  • 核心参数
    • corePoolSize:核心线程数。
    • maximumPoolSize:最大线程数。
    • keepAliveTime:空闲线程存活时间。
    • workQueue:任务队列(如 LinkedBlockingQueue)。
  • 应用场景
    • 管理线程资源,避免频繁创建销毁线程。
  • 示例
    1
    2
    3
    4
    ExecutorService executor = new ThreadPoolExecutor(
    2, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100)
    );
    executor.submit(() -> System.out.println("Task executed"));

2. ForkJoinPool

  • 特点:工作窃取算法,适合分治任务。
  • 应用场景
    • 并行计算(如大规模数组排序)。
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    ForkJoinPool pool = new ForkJoinPool();
    pool.invoke(new RecursiveTask<Integer>() {
    @Override
    protected Integer compute() {
    // 分治逻辑
    return null;
    }
    });

3. CompletableFuture(JDK 8+)

  • 特点:异步编程,支持链式调用和组合。
  • 应用场景
    • 非阻塞异步任务编排(如微服务调用聚合)。
  • 示例
    1
    2
    3
    CompletableFuture.supplyAsync(() -> "Hello")
    .thenApplyAsync(s -> s + " World")
    .thenAccept(System.out::println);

五、原子操作类

1. AtomicInteger/AtomicLong

  • 特点:CAS 实现原子操作。
  • 应用场景
    • 计数器、序号生成。
  • 示例
    1
    2
    AtomicInteger counter = new AtomicInteger(0);
    counter.incrementAndGet(); // 原子自增

2. AtomicReference

  • 特点:原子更新对象引用。
  • 应用场景
    • 无锁数据结构(如栈、队列)。
  • 示例
    1
    2
    AtomicReference<String> ref = new AtomicReference<>("old");
    ref.compareAndSet("old", "new"); // CAS 更新

3. LongAdder(JDK 8+)

  • 特点:分段累加,高并发下性能优于 AtomicLong
  • 应用场景
    • 高频统计(如实时点击量计数)。
  • 示例
    1
    2
    LongAdder adder = new LongAdder();
    adder.increment();

六、应用场景总结

场景 推荐 JUC 类
高并发缓存 ConcurrentHashMap
生产者-消费者 BlockingQueue
任务并行执行 ForkJoinPool
多线程等待统一信号 CountDownLatch/CyclicBarrier
资源池管理(如连接池) Semaphore
无锁算法实现 AtomicXXX 系列
异步任务编排 CompletableFuture

七、最佳实践

  1. 优先使用并发容器:替代 Collections.synchronizedXXX()
  2. 避免过早优化:在确实需要时再使用低级工具(如 AQS)。
  3. 注意资源清理:线程池使用后调用 shutdown()
  4. 合理设置线程池参数:根据任务类型(CPU/IO 密集型)调整大小。

通过合理选择 JUC 类,可以显著提升 Java 并发程序的性能和可维护性。