在多核處理器普及的今天,java.util.concurrent 包提供的高級並發組件是構建高性能多線程應用的基石。本文系統梳理並發集合、原子變量、並發隨機數三大核心組件的用法與原理。
java.util.concurrent 根據接口將集合分為三大類,均建立了 happens-before 關係,避免內存一致性錯誤。
ArrayBlockingQueue(有界)、LinkedBlockingQueue(可選有界)、SynchronousQueue(直接傳遞)。Map,新增 putIfAbsent、remove(key, value)、replace(key, old, new) 等原子方法。Collections.synchronizedMap。ConcurrentMap,提供 ceilingEntry、floorKey 等近似匹配。TreeMap。java.util.concurrent.atomic 包下的類(AtomicInteger、AtomicLong、AtomicReference 等)利用 CPU CAS 指令實現無鎖原子操作,讀寫語義等同 volatile。
get() / set():volatile 讀寫incrementAndGet() / decrementAndGet():原子增減compareAndSet(expect, update):CAS 核心,成功返回 truegetAndAdd(delta):原子加法並返回舊值import java.util.concurrent.atomic.AtomicInteger;
public class AtomicCounter {
private final AtomicInteger count = new AtomicInteger(0);
public void increment() { count.incrementAndGet(); }
public void decrement() { count.decrementAndGet(); }
public int value() { return count.get(); }
}
JDK 7 引入,解決 Math.random() 多線程爭用種子導致的性能瓶頸。每個線程持有獨立種子,無競爭、無共享狀態。
// 獲取當前線程專屬實例
ThreadLocalRandom random = ThreadLocalRandom.current();
// 生成 [4, 77) 之間的隨機整數
int r = random.nextInt(4, 77);
// 長整型、雙精度同理
long l = random.nextLong(100, 1000);
double d = random.nextDouble(0.0, 1.0);
| 指標 | Math.random() | ThreadLocalRandom |
|---|---|---|
| 線程爭用 | 高(共享 AtomicLong 種子) | 無(ThreadLocal 隔離) |
| 吞吐量 | 隨線程數線性下降 | 近乎水平擴展 |
AtomicLong/AtomicInteger,避免鎖開銷。ConcurrentHashMap,拒絕手寫同步包裝。ThreadLocalRandom。Random 實例,改用 ThreadLocalRandom.current()。