以下是对 Java 中 atomic 包下原子类、线程池以及线程协作工具的详细介绍,适用于并发编程场景下的知识整理。
1. java.util.concurrent.atomic 原子类
Java 提供了一系列原子操作类,位于 java.util.concurrent.atomic 包中,用于实现无锁线程安全操作。这些类基于 CAS(Compare and Swap)算法 实现。
主要类及用途:
| 类名 | 用途 |
|---|---|
AtomicInteger | 原子整型变量 |
AtomicLong | 原子长整型变量 |
AtomicBoolean | 原子布尔值 |
AtomicReference<T> | 原子引用对象 |
AtomicIntegerArray | 原子整型数组 |
AtomicStampedReference | 带版本戳的原子引用,解决 ABA 问题 |
AtomicMarkableReference | 标记位的原子引用 |
示例:
AtomicInteger atomicInt = new AtomicInteger(0);
boolean success = atomicInt.compareAndSet(0, 10); // 如果当前值是0,则设为10
特点:
- 线程安全
- 避免使用锁
- 适用于高并发计数器、状态标志等
2. 线程池(ThreadPool)
线程池通过复用线程减少创建销毁开销,提高系统响应速度和资源利用率。
创建方式:
Java 中通常使用 Executors 工厂类创建线程池,底层基于 ThreadPoolExecutor。
常见类型:
| 线程池类型 | 描述 |
|---|---|
newFixedThreadPool | 固定大小线程池,适合负载较重的服务器 |
newCachedThreadPool | 缓存线程池,自动回收空闲线程,适合执行短期异步任务 |
newSingleThreadExecutor | 单线程线程池,保证任务串行执行 |
newScheduledThreadPool | 支持定时和周期性任务执行 |
示例:
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(() -> System.out.println("Task executed"));
executor.shutdown();
核心参数说明(ThreadPoolExecutor):
| 参数 | 说明 |
|---|---|
| corePoolSize | 核心线程数 |
| maximumPoolSize | 最大线程数 |
| keepAliveTime | 空闲线程存活时间 |
| unit | 时间单位 |
| workQueue | 任务队列 |
| threadFactory | 线程工厂 |
| handler | 拒绝策略(如 AbortPolicy, CallerRunsPolicy 等) |
3. 线程协作工具类
Java 提供了多种线程协作机制,帮助多个线程协同完成任务。
① CountDownLatch
允许一个或多个线程等待其他线程完成操作。
使用场景:
- 多个线程并行处理任务后通知主线程继续执行
示例:
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
new Thread(() -> {
try {
Thread.sleep(1000);
} finally {
latch.countDown(); // 减1
}
}).start();
}
latch.await(); // 等待所有线程countDown完
System.out.println("All threads done");
② Semaphore
控制同时访问的线程数量,用于限流或资源池管理。
使用场景:
- 控制数据库连接池最大连接数
- 控制并发线程数量
示例:
Semaphore semaphore = new Semaphore(2); // 允许两个线程同时执行
semaphore.acquire(); // 获取许可
try {
// 执行任务
} finally {
semaphore.release(); // 释放许可
}
③ CyclicBarrier
让一组线程互相等待,直到所有线程都到达某个屏障点后再一起继续执行。
使用场景:
- 并发测试时统一启动多个线程
示例:
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All arrived"));
Runnable task = () -> {
System.out.println(Thread.currentThread().getName() + " arrived");
try {
barrier.await(); // 等待其他线程
} catch (Exception e) {
e.printStackTrace();
}
};
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
④ Exchanger
用于两个线程之间交换数据。
使用场景:
- 生产者消费者模式中交换缓冲区
示例:
Exchanger<String> exchanger = new Exchanger<>();
new Thread(() -> {
String data = "Data from Thread 1";
try {
String received = exchanger.exchange(data);
System.out.println("Received: " + received);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
String data = "Data from Thread 2";
try {
String received = exchanger.exchange(data);
System.out.println("Received: " + received);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
⑤ Phaser
比 CyclicBarrier 和 CountDownLatch 更灵活,支持动态注册线程、分阶段同步等。
使用场景:
- 多阶段任务协调(如并行计算中的多轮迭代)
示例:
Phaser phaser = new Phaser();
phaser.register(); // 注册主线程
for (int i = 0; i < 3; i++) {
phaser.register(); // 动态注册线程
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " phase 1 done");
phaser.arriveAndAwaitAdvance(); // 等待所有线程第一阶段完成
System.out.println(Thread.currentThread().getName() + " phase 2 done");
phaser.arriveAndAwaitAdvance();
}).start();
}
phaser.arriveAndDeregister(); // 主线程注销
总结对比表:
| 工具类 | 作用 | 是否可重复使用 | 是否支持动态调整 |
|---|---|---|---|
| CountDownLatch | 等待一组线程完成 | ❌ 不可重复使用 | ❌ 不支持 |
| Semaphore | 控制并发数量 | ✅ 可重复使用 | ❌ 不支持 |
| CyclicBarrier | 多线程互相等待 | ✅ 可重复使用 | ❌ 不支持 |
| Exchanger | 两线程间交换数据 | ✅ 可重复使用 | ❌ 不支持 |
| Phaser | 多阶段协调 | ✅ 可重复使用 | ✅ 支持动态注册 |
如果你有具体的业务场景或代码片段需要分析,我可以结合上下文进一步提供优化建议。