JAVA笔记之JUC
·
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. 同步工具类
| 类 | 用途 | 优势 |
|---|---|---|
|
|
等待 N 个任务完成 |
一次性,主线程等多线程 |
|
|
N 线程互相等待到齐 |
可循环复用 |
|
|
限流/控制并发数 |
比锁更轻量的资源计数 |
// 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.选用建议
| 场景 | 推荐 |
|---|---|
|
异步任务 |
|
|
等待多线程完成 |
|
|
限流 |
|
|
共享 Map |
|
|
生产者-消费者 |
|
|
简单计数 |
|
|
高并发计数 |
|
|
读多写少 |
|
核心原则:优先用 JUC 高级工具(线程池、并发容器、原子类),只在需要复杂条件等待或公平性时才用显式锁;始终记得关闭线程池、释放锁、清理 ThreadLocal。
更多推荐
所有评论(0)