Java 多线程完全指南

Java 多线程完全指南

目录

  1. 多线程基础
  2. 线程创建方式
  3. 线程生命周期
  4. 线程控制
  5. 线程同步
  6. 线程通信
  7. 锁机制
  8. 线程池
  9. 并发工具类
  10. 原子类
  11. 并发集合
  12. CompletableFuture
  13. 实战案例
  14. 最佳实践

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 拒绝策略
相关推荐
时艰.9 小时前
java性能调优 — 高并发缓存一致性
java·开发语言·缓存
jxy99989 小时前
mac mini 安装java JDK 17
java·开发语言·macos
biyezuopinvip9 小时前
基于Spring Boot的企业网盘的设计与实现(毕业论文)
java·spring boot·vue·毕业设计·论文·毕业论文·企业网盘的设计与实现
Hx_Ma169 小时前
SSM搭建(三)Spring整合SpringMVC框架
java·后端·spring
无风听海9 小时前
.NET10之ASP.NET Core的Filter管线
java·asp.net·.net
少许极端9 小时前
算法奇妙屋(二十八)-递归、回溯与剪枝的综合问题 1
java·算法·深度优先·剪枝·回溯·递归
Boop_wu9 小时前
简单介绍 JSON
java·开发语言
知识即是力量ol9 小时前
初识 Kafka(一):分布式流平台的定义、核心优势与架构全景
java·分布式·kafka·消息队列
爱吃生蚝的于勒9 小时前
【Linux】线程概念(一)
java·linux·运维·服务器·开发语言·数据结构·vim