java.util.concurrent(JUC)是 Java 并发编程的核心包,相比 synchronized + wait/notify,提供了更细粒度控制、更高性能、更清晰的 API。

1. 线程池 — ExecutorService / ThreadPoolExecutor

优势:复用线程、限制并发数、统一任务提交与关闭,避免频繁 new Thread()

ExecutorService pool = Executors.newFixedThreadPool(4);

// 生产环境推荐显式 ThreadPoolExecutor,便于设置队列、拒绝策略

Future<Integer> future = pool.submit(() -> 1 + 1);

System.out.println(future.get()); // 2

pool.shutdown();

2. 异步编排 — CompletableFuture

优势:链式回调、组合多个异步任务,替代嵌套 Future.get()

CompletableFuture.supplyAsync(() -> "Hello")
    .thenApply(s -> s + " JUC")
    .thenAccept(System.out::println) // Hello JUC
    .join();

3. 同步工具类

用途 优势

CountDownLatch

等待 N 个任务完成

一次性,主线程等多线程

CyclicBarrier

N 线程互相等待到齐

可循环复用

Semaphore

限流/控制并发数

比锁更轻量的资源计数

// CountDownLatch:3 个子任务都完成后再继续
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
    pool.execute(() -> { /* work */ latch.countDown(); });
}
latch.await(); // 主线程阻塞等待


// Semaphore:最多 5 个并发访问
Semaphore sem = new Semaphore(5);
sem.acquire();
try { 
    /* 访问资源 */
} finally { 
    sem.release(); 
}

4. 显式锁 — ReentrantLock / ReadWriteLock

优势:可中断、可超时、公平锁、读写分离(读多写少场景性能更好)。

ReentrantLock lock = new ReentrantLock();

lock.lock();

try {
    // 临界区
} finally {
    lock.unlock(); // 必须在 finally 释放
}

ReadWriteLock rw = new ReentrantReadWriteLock();

rw.readLock().lock(); // 多读共享

rw.writeLock().lock(); // 写独占

5. 并发容器 — ConcurrentHashMap / BlockingQueue

优势:线程安全且性能优于 Collections.synchronizedMap;阻塞队列天然支持生产者-消费者。

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

map.putIfAbsent("key", 1);

map.compute("key", (k, v) -> v + 1);

BlockingQueue<String> queue = new ArrayBlockingQueue<>(100);

queue.put("task"); // 生产者,队列满则阻塞

String task = queue.take(); // 消费者,队列空则阻塞

6. 原子类 — AtomicInteger / LongAdder

优势:CAS 无锁更新,比 synchronized 计数更高效;高并发计数推荐 LongAdder

AtomicInteger counter = new AtomicInteger(0);

counter.incrementAndGet(); // 原子 +1

counter.compareAndSet(1, 2); // CAS

LongAdder adder = new LongAdder(); // 分段累加,高并发更优

adder.increment();

long sum = adder.sum();

7. ThreadLocal

优势:线程隔离变量,避免共享状态;常用于无状态服务的上下文传递(注意内存泄漏,用完 remove())。

ThreadLocal<User> ctx = ThreadLocal.withInitial(() -> null);

ctx.set(currentUser);

try { 
    /* 本线程内随处 ctx.get() */
} finally { 
    ctx.remove(); 
}

8.选用建议

场景 推荐

异步任务

ExecutorService / CompletableFuture

等待多线程完成

CountDownLatch

限流

Semaphore

共享 Map

ConcurrentHashMap

生产者-消费者

BlockingQueue

简单计数

AtomicInteger

高并发计数

LongAdder

读多写少

ReadWriteLock

核心原则:优先用 JUC 高级工具(线程池、并发容器、原子类),只在需要复杂条件等待或公平性时才用显式锁;始终记得关闭线程池、释放锁、清理 ThreadLocal

更多推荐