Java 多线程完全指南
目录
多线程基础
线程创建方式
线程生命周期
线程控制
线程同步
线程通信
锁机制
线程池
并发工具类
原子类
并发集合
CompletableFuture
实战案例
最佳实践
1. 多线程基础
1.1 进程与线程
复制代码
进程(Process):
- 操作系统分配资源的基本单位
- 拥有独立的内存空间
- 进程间通信开销大
线程(Thread):
- CPU 调度的基本单位
- 共享进程的内存空间
- 线程间通信开销小
- 一个进程可以包含多个线程
1.2 并发与并行
复制代码
并发(Concurrency):
- 多个任务交替执行
- 单核 CPU 通过时间片轮转实现
- 宏观上同时,微观上交替
并行(Parallelism):
- 多个任务同时执行
- 需要多核 CPU 支持
- 真正的同时执行
1.3 多线程的优势
复制代码
1. 提高 CPU 利用率
2. 提高程序响应速度
3. 简化程序结构
4. 充分利用多核处理器
1.4 多线程的挑战
复制代码
1. 线程安全问题
2. 死锁问题
3. 资源竞争
4. 上下文切换开销
5. 调试困难
2. 线程创建方式
2.1 继承 Thread 类
java
复制代码
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
// 使用
MyThread thread = new MyThread();
thread.setName("MyThread");
thread.start(); // 启动线程,不是 run()
2.2 实现 Runnable 接口
java
复制代码
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
// 使用
Thread thread = new Thread(new MyRunnable(), "MyRunnable");
thread.start();
// Lambda 表达式
Thread thread2 = new Thread(() -> {
System.out.println("Lambda 线程");
});
thread2.start();
2.3 实现 Callable 接口
java
复制代码
public class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
}
// 使用 FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());
Thread thread = new Thread(futureTask);
thread.start();
// 获取结果(阻塞)
Integer result = futureTask.get();
System.out.println("结果: " + result);
// 带超时的获取
Integer result2 = futureTask.get(1, TimeUnit.SECONDS);
2.4 使用线程池
java
复制代码
ExecutorService executor = Executors.newFixedThreadPool(5);
// 提交 Runnable
executor.execute(() -> {
System.out.println("Runnable 任务");
});
// 提交 Callable
Future<String> future = executor.submit(() -> {
return "Callable 结果";
});
String result = future.get();
executor.shutdown();
2.5 创建方式对比
方式
优点
缺点
继承 Thread
简单直接
无法继承其他类
实现 Runnable
可继承其他类,适合资源共享
无返回值
实现 Callable
有返回值,可抛出异常
稍复杂
线程池
复用线程,管理方便
需要正确配置
3. 线程生命周期
3.1 线程状态
java
复制代码
public enum State {
NEW, // 新建:线程被创建但未启动
RUNNABLE, // 可运行:正在运行或等待 CPU 时间片
BLOCKED, // 阻塞:等待获取锁
WAITING, // 等待:无限期等待其他线程
TIMED_WAITING, // 超时等待:有时限的等待
TERMINATED // 终止:线程执行完毕
}
3.2 状态转换图
复制代码
start()
NEW ─────────────> RUNNABLE
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
BLOCKED WAITING TIMED_WAITING
│ │ │
└────────────┼────────────┘
│
▼
TERMINATED
3.3 状态转换示例
java
复制代码
Thread thread = new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println(thread.getState()); // NEW
thread.start();
System.out.println(thread.getState()); // RUNNABLE
Thread.sleep(100);
System.out.println(thread.getState()); // TIMED_WAITING
thread.join();
System.out.println(thread.getState()); // TERMINATED
3.4 获取线程状态
java
复制代码
Thread thread = new Thread(() -> {
// 线程逻辑
});
// 获取状态
Thread.State state = thread.getState();
// 判断是否存活
boolean alive = thread.isAlive();
// 判断是否中断
boolean interrupted = thread.isInterrupted();
4. 线程控制
4.1 线程休眠
java
复制代码
// 休眠指定毫秒
Thread.sleep(1000);
// 休眠指定时间
TimeUnit.SECONDS.sleep(1);
TimeUnit.MILLISECONDS.sleep(500);
4.2 线程让步
java
复制代码
// 让出 CPU 时间片,重新竞争
Thread.yield();
4.3 线程加入
java
复制代码
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("子线程: " + i);
}
});
thread.start();
thread.join(); // 等待 thread 执行完毕
System.out.println("主线程继续");
// 带超时的 join
thread.join(1000); // 最多等待 1 秒
4.4 线程中断
java
复制代码
Thread thread = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("工作中...");
Thread.sleep(1000);
} catch (InterruptedException e) {
// sleep 被中断会抛出异常并清除中断标志
System.out.println("收到中断信号");
Thread.currentThread().interrupt(); // 重新设置中断标志
break;
}
}
System.out.println("线程结束");
});
thread.start();
Thread.sleep(3000);
thread.interrupt(); // 发送中断信号
4.5 线程优先级
java
复制代码
Thread thread = new Thread(() -> {
// 线程逻辑
});
// 设置优先级(1-10,默认 5)
thread.setPriority(Thread.MAX_PRIORITY); // 10
thread.setPriority(Thread.MIN_PRIORITY); // 1
thread.setPriority(Thread.NORM_PRIORITY); // 5
// 获取优先级
int priority = thread.getPriority();
4.6 守护线程
java
复制代码
Thread daemon = new Thread(() -> {
while (true) {
System.out.println("守护线程运行中...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
});
daemon.setDaemon(true); // 设置为守护线程(必须在 start 之前)
daemon.start();
// 主线程结束后,守护线程自动结束
Thread.sleep(3000);
System.out.println("主线程结束");
5. 线程同步
5.1 线程安全问题
java
复制代码
// 不安全的计数器
public class UnsafeCounter {
private int count = 0;
public void increment() {
count++; // 非原子操作:读取、加1、写入
}
public int getCount() {
return count;
}
}
// 测试
UnsafeCounter counter = new UnsafeCounter();
for (int i = 0; i < 1000; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
counter.increment();
}
}).start();
}
// 结果可能小于 1000000
5.2 synchronized 关键字
java
复制代码
// 同步方法
public class SafeCounter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
// 同步代码块
public class SafeCounter2 {
private int count = 0;
private final Object lock = new Object();
public void increment() {
synchronized (lock) {
count++;
}
}
}
// 同步静态方法(锁定类对象)
public class SafeCounter3 {
private static int count = 0;
public static synchronized void increment() {
count++;
}
}
5.3 synchronized 原理
java
复制代码
// synchronized 的实现基于 Monitor(监视器)
// 每个对象都有一个 Monitor
// 同步代码块编译后:
// monitorenter // 获取锁
// ... // 同步代码
// monitorexit // 释放锁
// 锁的特性:
// 1. 可重入性:同一线程可以多次获取同一把锁
// 2. 非公平性:不保证等待时间最长的线程先获取锁
5.4 volatile 关键字
java
复制代码
public class VolatileExample {
private volatile boolean running = true;
public void stop() {
running = false; // 对其他线程立即可见
}
public void run() {
while (running) {
// 工作
}
}
}
// volatile 的作用:
// 1. 保证可见性:一个线程修改后,其他线程立即可见
// 2. 禁止指令重排序
// 3. 不保证原子性
5.5 双重检查锁定
java
复制代码
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (Singleton.class) {
if (instance == null) { // 第二次检查
instance = new Singleton();
}
}
}
return instance;
}
}
6. 线程通信
6.1 wait/notify/notifyAll
java
复制代码
public class WaitNotifyExample {
private final Object lock = new Object();
private boolean ready = false;
public void waitForReady() throws InterruptedException {
synchronized (lock) {
while (!ready) {
lock.wait(); // 释放锁并等待
}
System.out.println("收到通知,继续执行");
}
}
public void setReady() {
synchronized (lock) {
ready = true;
lock.notifyAll(); // 通知所有等待的线程
}
}
}
6.2 生产者-消费者模式
java
复制代码
public class ProducerConsumer {
private final Queue<Integer> queue = new LinkedList<>();
private final int capacity = 10;
public void produce(int value) throws InterruptedException {
synchronized (queue) {
while (queue.size() == capacity) {
queue.wait(); // 队列满,等待
}
queue.offer(value);
System.out.println("生产: " + value);
queue.notifyAll();
}
}
public int consume() throws InterruptedException {
synchronized (queue) {
while (queue.isEmpty()) {
queue.wait(); // 队列空,等待
}
int value = queue.poll();
System.out.println("消费: " + value);
queue.notifyAll();
return value;
}
}
}
6.3 使用 Condition
java
复制代码
public class ConditionExample {
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private final Queue<Integer> queue = new LinkedList<>();
private final int capacity = 10;
public void produce(int value) throws InterruptedException {
lock.lock();
try {
while (queue.size() == capacity) {
notFull.await();
}
queue.offer(value);
notEmpty.signal();
} finally {
lock.unlock();
}
}
public int consume() throws InterruptedException {
lock.lock();
try {
while (queue.isEmpty()) {
notEmpty.await();
}
int value = queue.poll();
notFull.signal();
return value;
} finally {
lock.unlock();
}
}
}
7. 锁机制
7.1 ReentrantLock
java
复制代码
public class ReentrantLockExample {
private final ReentrantLock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock(); // 必须在 finally 中释放锁
}
}
// 尝试获取锁
public boolean tryIncrement() {
if (lock.tryLock()) {
try {
count++;
return true;
} finally {
lock.unlock();
}
}
return false;
}
// 带超时的尝试获取锁
public boolean tryIncrementWithTimeout() throws InterruptedException {
if (lock.tryLock(1, TimeUnit.SECONDS)) {
try {
count++;
return true;
} finally {
lock.unlock();
}
}
return false;
}
// 可中断的获取锁
public void interruptibleIncrement() throws InterruptedException {
lock.lockInterruptibly();
try {
count++;
} finally {
lock.unlock();
}
}
}
7.2 公平锁与非公平锁
java
复制代码
// 非公平锁(默认)
ReentrantLock unfairLock = new ReentrantLock();
ReentrantLock unfairLock2 = new ReentrantLock(false);
// 公平锁
ReentrantLock fairLock = new ReentrantLock(true);
// 公平锁保证等待时间最长的线程先获取锁
// 但性能比非公平锁低
7.3 ReadWriteLock
java
复制代码
public class ReadWriteLockExample {
private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
private final Lock readLock = rwLock.readLock();
private final Lock writeLock = rwLock.writeLock();
private Map<String, String> cache = new HashMap<>();
// 读操作(可多个线程同时读)
public String get(String key) {
readLock.lock();
try {
return cache.get(key);
} finally {
readLock.unlock();
}
}
// 写操作(独占)
public void put(String key, String value) {
writeLock.lock();
try {
cache.put(key, value);
} finally {
writeLock.unlock();
}
}
}
7.4 StampedLock(Java 8+)
java
复制代码
public class StampedLockExample {
private final StampedLock lock = new StampedLock();
private double x, y;
// 写锁
public void move(double deltaX, double deltaY) {
long stamp = lock.writeLock();
try {
x += deltaX;
y += deltaY;
} finally {
lock.unlockWrite(stamp);
}
}
// 乐观读
public double distanceFromOrigin() {
long stamp = lock.tryOptimisticRead(); // 乐观读,不阻塞
double currentX = x, currentY = y;
if (!lock.validate(stamp)) { // 检查是否有写操作
stamp = lock.readLock(); // 升级为悲观读锁
try {
currentX = x;
currentY = y;
} finally {
lock.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
}
7.5 死锁
java
复制代码
// 死锁示例
public class DeadlockExample {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
System.out.println("持有 lock1,等待 lock2");
synchronized (lock2) {
System.out.println("持有 lock1 和 lock2");
}
}
}
public void method2() {
synchronized (lock2) {
System.out.println("持有 lock2,等待 lock1");
synchronized (lock1) {
System.out.println("持有 lock2 和 lock1");
}
}
}
}
// 避免死锁的方法:
// 1. 按固定顺序获取锁
// 2. 使用 tryLock 带超时
// 3. 使用死锁检测
8. 线程池
8.1 线程池概述
复制代码
线程池的优势:
1. 降低资源消耗:复用线程,减少创建销毁开销
2. 提高响应速度:任务到达时无需等待线程创建
3. 提高可管理性:统一管理、调优和监控
8.2 ThreadPoolExecutor
java
复制代码
// 核心构造方法
public ThreadPoolExecutor(
int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 空闲线程存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 工作队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler // 拒绝策略
)
// 创建线程池
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心线程数
10, // 最大线程数
60L, TimeUnit.SECONDS, // 空闲线程存活时间
new LinkedBlockingQueue<>(100), // 工作队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);
8.3 工作队列
java
复制代码
// 有界队列
new ArrayBlockingQueue<>(100);
new LinkedBlockingQueue<>(100);
// 无界队列(慎用,可能导致 OOM)
new LinkedBlockingQueue<>();
// 同步移交队列(不存储任务)
new SynchronousQueue<>();
// 优先级队列
new PriorityBlockingQueue<>();
8.4 拒绝策略
java
复制代码
// AbortPolicy(默认):抛出 RejectedExecutionException
new ThreadPoolExecutor.AbortPolicy();
// CallerRunsPolicy:由调用线程执行任务
new ThreadPoolExecutor.CallerRunsPolicy();
// DiscardPolicy:静默丢弃任务
new ThreadPoolExecutor.DiscardPolicy();
// DiscardOldestPolicy:丢弃队列中最老的任务
new ThreadPoolExecutor.DiscardOldestPolicy();
// 自定义拒绝策略
RejectedExecutionHandler customHandler = (r, executor) -> {
// 记录日志、持久化任务等
System.out.println("任务被拒绝: " + r.toString());
};
8.5 Executors 工厂方法
java
复制代码
// 固定大小线程池
ExecutorService fixed = Executors.newFixedThreadPool(10);
// 缓存线程池(线程数无上限)
ExecutorService cached = Executors.newCachedThreadPool();
// 单线程池
ExecutorService single = Executors.newSingleThreadExecutor();
// 调度线程池
ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(5);
// 工作窃取线程池(Java 8+)
ExecutorService workStealing = Executors.newWorkStealingPool();
// 注意:阿里巴巴规范建议使用 ThreadPoolExecutor 而非 Executors
8.6 线程池使用
java
复制代码
ExecutorService executor = Executors.newFixedThreadPool(5);
// 提交 Runnable
executor.execute(() -> {
System.out.println("执行任务");
});
// 提交 Callable
Future<String> future = executor.submit(() -> {
return "任务结果";
});
String result = future.get();
// 批量提交
List<Callable<Integer>> tasks = Arrays.asList(
() -> 1,
() -> 2,
() -> 3
);
List<Future<Integer>> futures = executor.invokeAll(tasks);
// 任意一个完成即返回
Integer first = executor.invokeAny(tasks);
// 关闭线程池
executor.shutdown(); // 平滑关闭,等待任务完成
executor.shutdownNow(); // 立即关闭,中断正在执行的任务
executor.awaitTermination(60, TimeUnit.SECONDS); // 等待关闭完成
8.7 ScheduledExecutorService
java
复制代码
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);
// 延迟执行
scheduler.schedule(() -> {
System.out.println("延迟 3 秒执行");
}, 3, TimeUnit.SECONDS);
// 固定频率执行
scheduler.scheduleAtFixedRate(() -> {
System.out.println("每 2 秒执行一次");
}, 0, 2, TimeUnit.SECONDS);
// 固定延迟执行
scheduler.scheduleWithFixedDelay(() -> {
System.out.println("上次执行完成后延迟 2 秒执行");
}, 0, 2, TimeUnit.SECONDS);
9. 并发工具类
9.1 CountDownLatch
java
复制代码
// 等待多个线程完成
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
final int index = i;
new Thread(() -> {
System.out.println("任务 " + index + " 完成");
latch.countDown(); // 计数减 1
}).start();
}
latch.await(); // 等待计数归零
System.out.println("所有任务完成");
// 带超时的等待
boolean completed = latch.await(10, TimeUnit.SECONDS);
9.2 CyclicBarrier
java
复制代码
// 多个线程互相等待
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("所有线程到达屏障");
});
for (int i = 0; i < 3; i++) {
final int index = i;
new Thread(() -> {
System.out.println("线程 " + index + " 到达屏障");
try {
barrier.await(); // 等待其他线程
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("线程 " + index + " 继续执行");
}).start();
}
// CyclicBarrier 可以重复使用
barrier.reset();
9.3 Semaphore
java
复制代码
// 信号量,控制并发访问数量
Semaphore semaphore = new Semaphore(3); // 最多 3 个线程同时访问
for (int i = 0; i < 10; i++) {
final int index = i;
new Thread(() -> {
try {
semaphore.acquire(); // 获取许可
System.out.println("线程 " + index + " 获取许可");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放许可
System.out.println("线程 " + index + " 释放许可");
}
}).start();
}
// 尝试获取许可
boolean acquired = semaphore.tryAcquire();
boolean acquiredWithTimeout = semaphore.tryAcquire(1, TimeUnit.SECONDS);
9.4 Exchanger
java
复制代码
// 两个线程交换数据
Exchanger<String> exchanger = new Exchanger<>();
new Thread(() -> {
try {
String data = "来自线程 A 的数据";
String received = exchanger.exchange(data);
System.out.println("线程 A 收到: " + received);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
String data = "来自线程 B 的数据";
String received = exchanger.exchange(data);
System.out.println("线程 B 收到: " + received);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
9.5 Phaser
java
复制代码
// 分阶段执行
Phaser phaser = new Phaser(3); // 3 个参与者
for (int i = 0; i < 3; i++) {
final int index = i;
new Thread(() -> {
System.out.println("线程 " + index + " 完成阶段 1");
phaser.arriveAndAwaitAdvance(); // 等待所有线程完成阶段 1
System.out.println("线程 " + index + " 完成阶段 2");
phaser.arriveAndAwaitAdvance(); // 等待所有线程完成阶段 2
System.out.println("线程 " + index + " 完成阶段 3");
phaser.arriveAndDeregister(); // 完成并注销
}).start();
}
10. 原子类
10.1 基本原子类
java
复制代码
// AtomicInteger
AtomicInteger atomicInt = new AtomicInteger(0);
atomicInt.get(); // 获取值
atomicInt.set(10); // 设置值
atomicInt.getAndSet(20); // 获取并设置
atomicInt.incrementAndGet(); // 自增并获取
atomicInt.getAndIncrement(); // 获取并自增
atomicInt.addAndGet(5); // 加并获取
atomicInt.compareAndSet(25, 30); // CAS 操作
atomicInt.updateAndGet(x -> x * 2); // 更新并获取
// AtomicLong
AtomicLong atomicLong = new AtomicLong(0L);
// AtomicBoolean
AtomicBoolean atomicBoolean = new AtomicBoolean(false);
10.2 原子引用
java
复制代码
// AtomicReference
AtomicReference<String> atomicRef = new AtomicReference<>("Hello");
atomicRef.compareAndSet("Hello", "World");
// AtomicStampedReference(解决 ABA 问题)
AtomicStampedReference<String> stampedRef =
new AtomicStampedReference<>("Hello", 0);
int[] stampHolder = new int[1];
String value = stampedRef.get(stampHolder);
stampedRef.compareAndSet("Hello", "World", stampHolder[0], stampHolder[0] + 1);
// AtomicMarkableReference
AtomicMarkableReference<String> markableRef =
new AtomicMarkableReference<>("Hello", false);
10.3 原子数组
java
复制代码
// AtomicIntegerArray
AtomicIntegerArray atomicArray = new AtomicIntegerArray(10);
atomicArray.get(0);
atomicArray.set(0, 100);
atomicArray.incrementAndGet(0);
atomicArray.compareAndSet(0, 101, 200);
// AtomicLongArray
AtomicLongArray atomicLongArray = new AtomicLongArray(10);
// AtomicReferenceArray
AtomicReferenceArray<String> atomicRefArray = new AtomicReferenceArray<>(10);
10.4 字段更新器
java
复制代码
public class FieldUpdaterExample {
private volatile int count;
private static final AtomicIntegerFieldUpdater<FieldUpdaterExample> updater =
AtomicIntegerFieldUpdater.newUpdater(FieldUpdaterExample.class, "count");
public void increment() {
updater.incrementAndGet(this);
}
}
10.5 LongAdder 和 LongAccumulator
java
复制代码
// LongAdder(高并发下比 AtomicLong 性能更好)
LongAdder adder = new LongAdder();
adder.increment();
adder.add(10);
long sum = adder.sum();
// LongAccumulator
LongAccumulator accumulator = new LongAccumulator(Long::max, 0);
accumulator.accumulate(10);
accumulator.accumulate(5);
long result = accumulator.get(); // 10
11. 并发集合
11.1 ConcurrentHashMap
java
复制代码
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// 基本操作
map.put("key", 1);
map.get("key");
map.remove("key");
// 原子操作
map.putIfAbsent("key", 1);
map.computeIfAbsent("key", k -> 1);
map.computeIfPresent("key", (k, v) -> v + 1);
map.compute("key", (k, v) -> v == null ? 1 : v + 1);
map.merge("key", 1, Integer::sum);
// 批量操作
map.forEach((k, v) -> System.out.println(k + ": " + v));
map.search(1, (k, v) -> v > 10 ? k : null);
map.reduce(1, (k, v) -> v, Integer::sum);
11.2 CopyOnWriteArrayList
java
复制代码
// 适用于读多写少的场景
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("item1");
list.add("item2");
// 迭代时可以修改(不会抛出 ConcurrentModificationException)
for (String item : list) {
if (item.equals("item1")) {
list.remove(item); // 安全
}
}
11.3 ConcurrentLinkedQueue
java
复制代码
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.offer("item1");
queue.offer("item2");
String item = queue.poll();
String peek = queue.peek();
11.4 BlockingQueue
java
复制代码
// ArrayBlockingQueue(有界)
BlockingQueue<String> arrayQueue = new ArrayBlockingQueue<>(100);
// LinkedBlockingQueue(可选有界)
BlockingQueue<String> linkedQueue = new LinkedBlockingQueue<>(100);
// PriorityBlockingQueue(优先级)
BlockingQueue<String> priorityQueue = new PriorityBlockingQueue<>();
// 阻塞操作
arrayQueue.put("item"); // 队列满时阻塞
String item = arrayQueue.take(); // 队列空时阻塞
// 超时操作
arrayQueue.offer("item", 1, TimeUnit.SECONDS);
String item2 = arrayQueue.poll(1, TimeUnit.SECONDS);
11.5 ConcurrentSkipListMap/Set
java
复制代码
// 并发有序 Map
ConcurrentSkipListMap<String, Integer> skipListMap = new ConcurrentSkipListMap<>();
skipListMap.put("b", 2);
skipListMap.put("a", 1);
skipListMap.put("c", 3);
// 遍历时有序
// 并发有序 Set
ConcurrentSkipListSet<String> skipListSet = new ConcurrentSkipListSet<>();
12. CompletableFuture
12.1 创建 CompletableFuture
java
复制代码
// 创建已完成的 Future
CompletableFuture<String> completed = CompletableFuture.completedFuture("result");
// 异步执行(无返回值)
CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
System.out.println("异步执行");
});
// 异步执行(有返回值)
CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> {
return "异步结果";
});
// 使用自定义线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
CompletableFuture<String> customAsync = CompletableFuture.supplyAsync(() -> {
return "自定义线程池";
}, executor);
12.2 结果处理
java
复制代码
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello");
// thenApply:转换结果
CompletableFuture<Integer> lengthFuture = future.thenApply(String::length);
// thenAccept:消费结果
future.thenAccept(System.out::println);
// thenRun:执行后续操作(不使用结果)
future.thenRun(() -> System.out.println("完成"));
// 异步版本
future.thenApplyAsync(String::length);
future.thenAcceptAsync(System.out::println);
future.thenRunAsync(() -> System.out.println("完成"));
12.3 组合操作
java
复制代码
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");
// thenCompose:扁平化组合
CompletableFuture<String> composed = future1.thenCompose(s ->
CompletableFuture.supplyAsync(() -> s + " World"));
// thenCombine:合并两个结果
CompletableFuture<String> combined = future1.thenCombine(future2,
(s1, s2) -> s1 + " " + s2);
// allOf:等待所有完成
CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2);
// anyOf:任意一个完成
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2);
12.4 异常处理
java
复制代码
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
if (true) throw new RuntimeException("错误");
return "result";
});
// exceptionally:处理异常
CompletableFuture<String> handled = future.exceptionally(ex -> {
System.out.println("异常: " + ex.getMessage());
return "默认值";
});
// handle:处理结果或异常
CompletableFuture<String> handleFuture = future.handle((result, ex) -> {
if (ex != null) {
return "异常: " + ex.getMessage();
}
return result;
});
// whenComplete:完成时回调(不改变结果)
future.whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("异常: " + ex.getMessage());
} else {
System.out.println("结果: " + result);
}
});
12.5 获取结果
java
复制代码
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "result");
// 阻塞获取
String result = future.get();
// 带超时获取
String result2 = future.get(1, TimeUnit.SECONDS);
// 立即获取(未完成返回默认值)
String result3 = future.getNow("default");
// join(不抛出受检异常)
String result4 = future.join();
13. 实战案例
13.1 线程安全的单例模式
java
复制代码
// 双重检查锁定
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
// 静态内部类
public class Singleton2 {
private Singleton2() {}
private static class Holder {
private static final Singleton2 INSTANCE = new Singleton2();
}
public static Singleton2 getInstance() {
return Holder.INSTANCE;
}
}
// 枚举(推荐)
public enum Singleton3 {
INSTANCE;
public void doSomething() {
// ...
}
}
13.2 线程池最佳实践
java
复制代码
public class ThreadPoolManager {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// CPU 密集型任务
public static ExecutorService createCpuIntensivePool() {
return new ThreadPoolExecutor(
CPU_COUNT + 1,
CPU_COUNT + 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(100),
new ThreadFactoryBuilder().setNameFormat("cpu-pool-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
// IO 密集型任务
public static ExecutorService createIoIntensivePool() {
return new ThreadPoolExecutor(
CPU_COUNT * 2,
CPU_COUNT * 2,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(200),
new ThreadFactoryBuilder().setNameFormat("io-pool-%d").build(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
}
13.3 并发任务处理
java
复制代码
public class ConcurrentTaskProcessor {
private final ExecutorService executor;
public ConcurrentTaskProcessor(int threads) {
this.executor = Executors.newFixedThreadPool(threads);
}
// 并行处理列表
public <T, R> List<R> processInParallel(List<T> items, Function<T, R> processor) {
List<CompletableFuture<R>> futures = items.stream()
.map(item -> CompletableFuture.supplyAsync(() -> processor.apply(item), executor))
.collect(Collectors.toList());
return futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
}
// 带超时的并行处理
public <T, R> List<R> processWithTimeout(List<T> items, Function<T, R> processor,
long timeout, TimeUnit unit) throws Exception {
List<Callable<R>> tasks = items.stream()
.map(item -> (Callable<R>) () -> processor.apply(item))
.collect(Collectors.toList());
List<Future<R>> futures = executor.invokeAll(tasks, timeout, unit);
return futures.stream()
.map(f -> {
try {
return f.get();
} catch (Exception e) {
return null;
}
})
.collect(Collectors.toList());
}
public void shutdown() {
executor.shutdown();
}
}
13.4 限流器
java
复制代码
public class RateLimiter {
private final Semaphore semaphore;
private final int permitsPerSecond;
private final ScheduledExecutorService scheduler;
public RateLimiter(int permitsPerSecond) {
this.permitsPerSecond = permitsPerSecond;
this.semaphore = new Semaphore(permitsPerSecond);
this.scheduler = Executors.newSingleThreadScheduledExecutor();
// 每秒重置许可
scheduler.scheduleAtFixedRate(() -> {
int permitsToRelease = permitsPerSecond - semaphore.availablePermits();
if (permitsToRelease > 0) {
semaphore.release(permitsToRelease);
}
}, 1, 1, TimeUnit.SECONDS);
}
public boolean tryAcquire() {
return semaphore.tryAcquire();
}
public void acquire() throws InterruptedException {
semaphore.acquire();
}
public void shutdown() {
scheduler.shutdown();
}
}
14. 最佳实践
14.1 线程安全原则
java
复制代码
// ✅ 使用不可变对象
public final class ImmutableUser {
private final String name;
private final int age;
public ImmutableUser(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
// ✅ 使用线程安全的集合
Map<String, String> map = new ConcurrentHashMap<>();
List<String> list = new CopyOnWriteArrayList<>();
// ✅ 使用原子类
AtomicInteger counter = new AtomicInteger(0);
14.2 锁使用原则
java
复制代码
// ✅ 缩小锁的范围
public void process() {
// 不需要同步的代码
prepareData();
synchronized (lock) {
// 只同步必要的代码
updateSharedState();
}
// 不需要同步的代码
cleanup();
}
// ✅ 使用 try-finally 确保释放锁
Lock lock = new ReentrantLock();
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock();
}
// ✅ 避免嵌套锁
// ❌ 容易死锁
synchronized (lock1) {
synchronized (lock2) {
// ...
}
}
14.3 线程池使用原则
java
复制代码
// ✅ 使用 ThreadPoolExecutor 而非 Executors
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
keepAliveTime, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(queueSize),
threadFactory,
rejectedHandler
);
// ✅ 为线程池命名
ThreadFactory namedFactory = new ThreadFactoryBuilder()
.setNameFormat("my-pool-%d")
.build();
// ✅ 正确关闭线程池
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
14.4 避免常见问题
java
复制代码
// ❌ 不要在循环中创建线程
for (int i = 0; i < 1000; i++) {
new Thread(() -> { /* ... */ }).start(); // 错误
}
// ✅ 使用线程池
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 1000; i++) {
executor.execute(() -> { /* ... */ });
}
// ❌ 不要忽略 InterruptedException
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// 不要忽略
}
// ✅ 正确处理中断
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 重新设置中断标志
// 或者抛出异常
}
附录:多线程速查表
线程状态
状态
说明
NEW
新建,未启动
RUNNABLE
可运行,正在运行或等待 CPU
BLOCKED
阻塞,等待获取锁
WAITING
等待,无限期等待
TIMED_WAITING
超时等待,有时限等待
TERMINATED
终止,执行完毕
常用并发工具
工具
用途
CountDownLatch
等待多个线程完成
CyclicBarrier
多个线程互相等待
Semaphore
控制并发访问数量
Exchanger
两个线程交换数据
Phaser
分阶段执行
线程池参数
参数
说明
corePoolSize
核心线程数
maximumPoolSize
最大线程数
keepAliveTime
空闲线程存活时间
workQueue
工作队列
threadFactory
线程工厂
handler
拒绝策略