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 类
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 接口
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 接口
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 使用线程池
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 线程状态
public enum State {
NEW, // 新建:线程被创建但未启动
RUNNABLE, // 可运行:正在运行或等待 CPU 时间片
BLOCKED, // 阻塞:等待获取锁
WAITING, // 等待:无限期等待其他线程
TIMED_WAITING, // 超时等待:有时限的等待
TERMINATED // 终止:线程执行完毕
}
3.2 状态转换图
start()
NEW ─────────────> RUNNABLE
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
BLOCKED WAITING TIMED_WAITING
│ │ │
└────────────┼────────────┘
│
▼
TERMINATED
3.3 状态转换示例
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 获取线程状态
Thread thread = new Thread(() -> {
// 线程逻辑
});
// 获取状态
Thread.State state = thread.getState();
// 判断是否存活
boolean alive = thread.isAlive();
// 判断是否中断
boolean interrupted = thread.isInterrupted();
4. 线程控制
4.1 线程休眠
// 休眠指定毫秒
Thread.sleep(1000);
// 休眠指定时间
TimeUnit.SECONDS.sleep(1);
TimeUnit.MILLISECONDS.sleep(500);
4.2 线程让步
// 让出 CPU 时间片,重新竞争
Thread.yield();
4.3 线程加入
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 线程中断
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 线程优先级
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 守护线程
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 线程安全问题
// 不安全的计数器
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 关键字
// 同步方法
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 原理
// synchronized 的实现基于 Monitor(监视器)
// 每个对象都有一个 Monitor
// 同步代码块编译后:
// monitorenter // 获取锁
// ... // 同步代码
// monitorexit // 释放锁
// 锁的特性:
// 1. 可重入性:同一线程可以多次获取同一把锁
// 2. 非公平性:不保证等待时间最长的线程先获取锁
5.4 volatile 关键字
public class VolatileExample {
private volatile boolean running = true;
public void stop() {
running = false; // 对其他线程立即可见
}
public void run() {
while (running) {
// 工作
}
}
}
// volatile 的作用:
// 1. 保证可见性:一个线程修改后,其他线程立即可见
// 2. 禁止指令重排序
// 3. 不保证原子性
5.5 双重检查锁定
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
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 生产者-消费者模式
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
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
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 公平锁与非公平锁
// 非公平锁(默认)
ReentrantLock unfairLock = new ReentrantLock();
ReentrantLock unfairLock2 = new ReentrantLock(false);
// 公平锁
ReentrantLock fairLock = new ReentrantLock(true);
// 公平锁保证等待时间最长的线程先获取锁
// 但性能比非公平锁低
7.3 ReadWriteLock
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+)
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 死锁
// 死锁示例
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
// 核心构造方法
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 工作队列
// 有界队列
new ArrayBlockingQueue<>(100);
new LinkedBlockingQueue<>(100);
// 无界队列(慎用,可能导致 OOM)
new LinkedBlockingQueue<>();
// 同步移交队列(不存储任务)
new SynchronousQueue<>();
// 优先级队列
new PriorityBlockingQueue<>();
8.4 拒绝策略
// 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 工厂方法
// 固定大小线程池
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 线程池使用
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
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
// 等待多个线程完成
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
// 多个线程互相等待
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
// 信号量,控制并发访问数量
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
// 两个线程交换数据
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
// 分阶段执行
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 基本原子类
// 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 原子引用
// 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 原子数组
// 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 字段更新器
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
// 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
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
// 适用于读多写少的场景
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
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.offer("item1");
queue.offer("item2");
String item = queue.poll();
String peek = queue.peek();
11.4 BlockingQueue
// 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
// 并发有序 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
// 创建已完成的 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 结果处理
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 组合操作
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 异常处理
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 获取结果
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 线程安全的单例模式
// 双重检查锁定
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 线程池最佳实践
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 并发任务处理
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 限流器
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 线程安全原则
// ✅ 使用不可变对象
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 锁使用原则
// ✅ 缩小锁的范围
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 线程池使用原则
// ✅ 使用 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 避免常见问题
// ❌ 不要在循环中创建线程
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 |
拒绝策略 |