跳到主要内容

Java 线程与并发编程概览

"并发编程是Java进阶的必经之路" —— 理解线程原理,掌握并发工具,构建高性能多线程应用

🎯 快速索引

🚀 为什么需要并发编程?

在多核CPU时代,并发编程是提升应用性能的关键手段:

// ❌ 串行处理 - 性能瓶颈
public class SequentialProcessor {
public List<Result> processData(List<Task> tasks) {
List<Result> results = new ArrayList<>();
for (Task task : tasks) {
results.add(processTask(task)); // 逐个处理,无法利用多核
}
return results;
}
}

// ✅ 并行处理 - 性能提升
public class ParallelProcessor {
private final ExecutorService executor = Executors.newFixedThreadPool(8);

public CompletableFuture<List<Result>> processData(List<Task> tasks) {
List<CompletableFuture<Result>> futures = tasks.stream()
.map(task -> CompletableFuture.supplyAsync(() -> processTask(task), executor))
.collect(Collectors.toList());

return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.thenApply(v -> futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList()));
}
}

并发编程的核心价值

  • 📈 性能提升:充分利用多核CPU,提升程序吞吐量
  • 🔄 响应性:避免阻塞主线程,提升用户体验
  • 🏗️ 模块化:将复杂任务分解为独立子任务
  • 📡 资源利用:合理管理I/O、网络等资源等待时间
  • ⚡ 实时性:满足实时系统对响应时间的要求

🏗️ 线程与进程基础

进程 vs 线程对比

特性进程线程
内存空间独立地址空间,相互隔离共享进程内存空间
创建成本高,需要分配独立资源低,共享进程资源
切换成本高,需要切换页表、上下文低,只需切换寄存器和栈
通信方式IPC(管道、Socket、共享内存)共享内存、信号量
健壮性一个进程崩溃不影响其他进程一个线程崩溃可能导致整个进程崩溃
适用场景多个独立程序运行单个程序内并行执行

Java线程的内存模型

🔧 Java线程体系架构

线程创建方式演进

// 1. 继承Thread类(不推荐,限制了继承)
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running: " + Thread.currentThread().getName());
}
}

// 2. 实现Runnable接口(推荐)
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable running: " + Thread.currentThread().getName());
}
}

// 3. 实现Callable接口(支持返回值)
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "Callable result: " + Thread.currentThread().getName();
}
}

// 4. 使用线程池(最佳实践)
ExecutorService executor = Executors.newFixedThreadPool(4);

// 提交Runnable任务
executor.submit(() -> System.out.println("Task in thread pool"));

// 提交Callable任务
Future<String> future = executor.submit(new MyCallable());
String result = future.get();

Thread核心API体系

🎯 并发编程核心概念

并发的三大特性

特性定义Java中的保证机制违反后果
原子性操作不可分割,要么全部执行,要么都不执行synchronizedvolatileAtomic类、Lock数据竞争、结果不一致
可见性一个线程的修改对其他线程立即可见volatilesynchronizedfinal字段脏读、数据过期
有序性程序执行的顺序按照代码的先后顺序执行volatilesynchronized、Happens-Before原则指令重排导致的异常

代码示例:三大特性的重要性

public class ConcurrencyIssues {

// ❌ 原子性问题:i++不是原子操作
private int counter = 0;
public void increment() {
counter++; // 实际包含读-改-写三个操作
}

// ❌ 可见性问题:变量可能不会被其他线程及时看到
private boolean flag = false;
public void setFlag() {
flag = true; // 可能不会被其他线程立即看到
}

// ❌ 有序性问题:指令重排可能导致意外结果
private boolean initialized = false;
private Resource resource;

public void initialize() {
resource = new Resource(); // 步骤1
initialized = true; // 步骤2,可能被重排到步骤1之前
}

public void useResource() {
if (initialized) {
resource.use(); // 可能获得null资源
}
}

// ✅ 解决方案
private final AtomicInteger atomicCounter = new AtomicInteger(0);
private volatile boolean volatileFlag = false;
private final Object lock = new Object();

public void safeIncrement() {
atomicCounter.incrementAndGet(); // 原子操作
}

public void safeSetFlag() {
synchronized (lock) {
volatileFlag = true; // 可见性保证
}
}

public void safeInitialize() {
synchronized (lock) {
resource = new Resource();
initialized = true; // 有序性保证
}
}
}

🧠 Java内存模型(JMM)

JMM核心概念

Java内存模型定义了线程和主内存之间的抽象关系:

Happens-Before原则

Happens-Before是JMM中最重要的概念,定义了操作之间的偏序关系:

public class HappensBeforeRules {

// 1. 程序次序规则:单线程内按代码顺序执行
public void programOrder() {
int a = 1; // 操作1
int b = 2; // 操作2, happens-before 操作3
int c = a + b; // 操作3
}

// 2. 监视器锁规则:unlock happens-before 同一个锁的lock
private final Object lock = new Object();
private int sharedVar;

public void unlockMethod() {
synchronized (lock) {
sharedVar = 1; // unlock操作
} // unlock happens-before 下一个lock
}

public void lockMethod() {
synchronized (lock) { // lock操作
System.out.println(sharedVar); // 能看到之前的修改
}
}

// 3. volatile变量规则:写操作 happens-before 读操作
private volatile boolean flag = false;
private int data = 0;

public void writer() {
data = 42; // 操作1
flag = true; // volatile写,happens-before volatile读
}

public void reader() {
if (flag) { // volatile读
System.out.println(data); // 一定能看到data=42
}
}

// 4. 线程启动规则:start() happens-before 线程中的任何操作
private Thread thread;

public void startThread() {
sharedVar = 100; // 操作1
thread.start(); // start() happens-before 线程内操作
}

// 5. 线程终止规则:线程中的所有操作 happens-before join()返回
public void joinThread() throws InterruptedException {
thread.join(); // 能看到线程内所有操作
}

// 6. 线程中断规则:interrupt() happens-before 检测到中断
public void interruptExample() {
thread.interrupt(); // interrupt() happens-before 检测中断
}

// 7. 对象终结规则:构造函数 happens-before finalize()
}

🔒 同步机制与锁

锁的分类与特性

锁类型特点性能适用场景
synchronizedJVM内置,自动获取释放优化后性能良好一般同步需求
ReentrantLockAPI级别,功能丰富略低于synchronized需要公平锁、可中断、超时
ReadWriteLock读写分离,读读不互斥读多写少场景性能好读多写少的场景
StampedLock乐观读,性能最优性能最好读远多于写的场景

锁的性能演进

public class LockPerformanceEvolution {

// JDK 1.6之前:重量级锁
// 所有同步都依赖操作系统互斥量,性能较差

// JDK 1.6+:锁优化
private final Object lock = new Object();
private volatile int sharedCounter;

// 偏向锁:第一个线程获取锁后,锁偏向该线程
public void biasedLockExample() {
synchronized (lock) { // 第一个线程获取锁
sharedCounter++; // 锁偏向该线程,后续获取无开销
}
}

// 轻量级锁:自旋等待,避免线程阻塞
public void lightweightLockExample() {
synchronized (lock) { // 短暂竞争时自旋
sharedCounter++; // 避免线程上下文切换
}
}

// 重量级锁:竞争激烈时阻塞线程
public void heavyweightLockExample() {
synchronized (lock) { // 激烈竞争时
// 长时间持有锁的代码
heavyOperation();
}
}

private void heavyOperation() {
// 模拟耗时操作
}

// 锁升级:偏向锁 -> 轻量级锁 -> 重量级锁
}

🛠️ 并发工具类框架

JUC工具类体系

常用并发工具类

public class ConcurrentToolsDemo {

// 1. CountDownLatch:倒计时门闩
public void countDownLatchExample() throws InterruptedException {
int threadCount = 5;
CountDownLatch startLatch = new CountDownLatch(1); // 启动信号
CountDownLatch completeLatch = new CountDownLatch(threadCount); // 完成信号

// 创建多个工作线程
for (int i = 0; i < threadCount; i++) {
new Thread(() -> {
try {
startLatch.await(); // 等待启动信号
doWork();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
completeLatch.countDown(); // 完成后倒计时
}
}).start();
}

startLatch.countDown(); // 发出启动信号
completeLatch.await(); // 等待所有线程完成
}

// 2. CyclicBarrier:循环屏障
public void cyclicBarrierExample() {
int parties = 3;
CyclicBarrier barrier = new CyclicBarrier(parties, () -> {
System.out.println("所有线程到达屏障点,执行屏障动作");
});

for (int i = 0; i < parties; i++) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + " 正在执行任务");
barrier.await(); // 等待其他线程
System.out.println(Thread.currentThread().getName() + " 继续执行");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}

// 3. Semaphore:信号量
public void semaphoreExample() {
int permits = 3; // 只允许3个线程同时访问
Semaphore semaphore = new Semaphore(permits);

for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
semaphore.acquire(); // 获取许可
System.out.println(Thread.currentThread().getName() + " 获取许可,访问资源");
Thread.sleep(1000); // 模拟资源访问
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release(); // 释放许可
System.out.println(Thread.currentThread().getName() + " 释放许可");
}
}).start();
}
}

private void doWork() {
System.out.println(Thread.currentThread().getName() + " 正在工作");
}
}

🏭 线程池与执行器

ThreadPoolExecutor核心参数

public class ThreadPoolAnalysis {

// 完整参数构造器
public ThreadPoolExecutor createThreadPool() {
return new ThreadPoolExecutor(
5, // corePoolSize: 核心线程数
10, // maximumPoolSize: 最大线程数
60L, // keepAliveTime: 空闲线程存活时间
TimeUnit.SECONDS, // 时间单位
new LinkedBlockingQueue<>(100), // 工作队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);
}

// 线程池执行流程
public void executionFlow() {
/*
1. 如果线程数 < corePoolSize:创建新线程执行任务
2. 如果线程数 >= corePoolSize 且队列未满:任务入队
3. 如果队列已满且线程数 < maximumPoolSize:创建新线程执行任务
4. 如果队列已满且线程数 >= maximumPoolSize:执行拒绝策略
*/
}

// 四种拒绝策略
public void rejectionPolicies() {
// 1. AbortPolicy:抛异常(默认)
ThreadPoolExecutor.AbortPolicy abortPolicy = new ThreadPoolExecutor.AbortPolicy();

// 2. CallerRunsPolicy:由调用线程执行任务
ThreadPoolExecutor.CallerRunsPolicy callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();

// 3. DiscardPolicy:直接丢弃任务
ThreadPoolExecutor.DiscardPolicy discardPolicy = new ThreadPoolExecutor.DiscardPolicy();

// 4. DiscardOldestPolicy:丢弃队列最老的任务
ThreadPoolExecutor.DiscardOldestPolicy discardOldestPolicy = new ThreadPoolExecutor.DiscardOldestPolicy();
}
}

线程池类型对比

线程池类型特点适用场景注意事项
FixedThreadPool固定大小,无界队列长期稳定任务队列可能堆积
CachedThreadPool可缓存,无上限数量短期大量任务可能创建过多线程
SingleThreadExecutor单线程,顺序执行顺序性要求高性能受限
ScheduledThreadPool定时任务,周期执行定时调度时间精度问题
WorkStealingPool工作窃取,ForkJoinCPU密集型任务JDK 8+

💼 实战应用场景

1. 生产者-消费者模式

public class ProducerConsumerPattern {

// 使用BlockingQueue实现
private final BlockingQueue<Task> queue = new ArrayBlockingQueue<>(100);
private final ExecutorService producerExecutor = Executors.newFixedThreadPool(3);
private final ExecutorService consumerExecutor = Executors.newFixedThreadPool(5);

public void startProducers() {
for (int i = 0; i < 3; i++) {
producerExecutor.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Task task = produceTask();
queue.put(task); // 队列满时阻塞
System.out.println("生产任务: " + task.getId());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
});
}
}

public void startConsumers() {
for (int i = 0; i < 5; i++) {
consumerExecutor.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Task task = queue.take(); // 队列空时阻塞
processTask(task);
System.out.println("消费任务: " + task.getId());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
});
}
}

private Task produceTask() {
return new Task(UUID.randomUUID().toString());
}

private void processTask(Task task) {
// 处理任务逻辑
}

static class Task {
private final String id;
public Task(String id) { this.id = id; }
public String getId() { return id; }
}
}

2. 并行计算框架

public class ParallelComputing {

// ForkJoinPool示例:并行计算数组总和
public class SumTask extends RecursiveTask<Long> {
private final long[] array;
private final int start;
private final int end;
private static final int THRESHOLD = 10000;

public SumTask(long[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}

@Override
protected Long compute() {
if (end - start <= THRESHOLD) {
// 小任务直接计算
long sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
// 大任务分解
int mid = (start + end) >>> 1;
SumTask left = new SumTask(array, start, mid);
SumTask right = new SumTask(array, mid, end);

left.fork(); // 异步执行左半部分
return right.compute() + left.join(); // 等待结果并合并
}
}
}

public long parallelSum(long[] array) {
ForkJoinPool pool = new ForkJoinPool();
try {
return pool.invoke(new SumTask(array, 0, array.length));
} finally {
pool.shutdown();
}
}

// 并行流处理
public void parallelStreamExample() {
List<Integer> numbers = IntStream.range(1, 1000000)
.boxed()
.collect(Collectors.toList());

// 并行计算
long sum = numbers.parallelStream()
.mapToLong(Integer::longValue)
.filter(n -> n % 2 == 0)
.sum();

System.out.println("并行计算结果: " + sum);
}
}

3. 异步编程模式

public class AsyncProgramming {

// CompletableFuture异步编程
public CompletableFuture<String> asyncExample() {
return CompletableFuture.supplyAsync(() -> {
// 异步任务1:获取用户信息
return fetchUserInfo();
}).thenApplyAsync(userInfo -> {
// 异步任务2:根据用户信息获取订单
return fetchUserOrders(userInfo);
}).thenApplyAsync(orders -> {
// 异步任务3:处理订单数据
return processOrders(orders);
}).exceptionally(ex -> {
// 异常处理
System.err.println("异步执行失败: " + ex.getMessage());
return "默认结果";
});
}

// 多个异步任务组合
public CompletableFuture<Void> combineAsyncTasks() {
CompletableFuture<String> task1 = CompletableFuture.supplyAsync(this::fetchUserData);
CompletableFuture<String> task2 = CompletableFuture.supplyAsync(this::fetchProductData);
CompletableFuture<String> task3 = CompletableFuture.supplyAsync(this::fetchOrderData);

return CompletableFuture.allOf(task1, task2, task3)
.thenRun(() -> {
try {
String userData = task1.get();
String productData = task2.get();
String orderData = task3.get();
System.out.println("所有数据获取完成");
} catch (InterruptedException | ExecutionException e) {
Thread.currentThread().interrupt();
}
});
}

private String fetchUserInfo() { return "用户信息"; }
private String fetchUserOrders(String userInfo) { return "订单数据"; }
private String processOrders(String orders) { return "处理结果"; }
private String fetchUserData() { return "用户数据"; }
private String fetchProductData() { return "产品数据"; }
private String fetchOrderData() { return "订单数据"; }
}

⚠️ 常见并发陷阱

1. 死锁问题

public class DeadlockExample {

private final Object lock1 = new Object();
private final Object lock2 = new Object();

// ❌ 可能产生死锁
public void potentialDeadlock() {
Thread thread1 = new Thread(() -> {
synchronized (lock1) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
synchronized (lock2) { // 可能永远等待
System.out.println("Thread 1: 获取了两个锁");
}
}
});

Thread thread2 = new Thread(() -> {
synchronized (lock2) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
synchronized (lock1) { // 可能永远等待
System.out.println("Thread 2: 获取了两个锁");
}
}
});

thread1.start();
thread2.start();
}

// ✅ 避免死锁:按固定顺序获取锁
public void avoidDeadlock() {
Thread thread1 = new Thread(() -> {
synchronized (lock1) { // 总是先获取lock1
synchronized (lock2) {
System.out.println("Thread 1: 获取了两个锁");
}
}
});

Thread thread2 = new Thread(() -> {
synchronized (lock1) { // 总是先获取lock1
synchronized (lock2) {
System.out.println("Thread 2: 获取了两个锁");
}
}
});

thread1.start();
thread2.start();
}

// ✅ 使用tryLock避免死锁
public void tryLockExample() {
ReentrantLock lock1 = new ReentrantLock();
ReentrantLock lock2 = new ReentrantLock();

Thread thread1 = new Thread(() -> {
while (true) {
if (lock1.tryLock()) {
try {
if (lock2.tryLock()) {
try {
System.out.println("Thread 1: 获取了两个锁");
break;
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
Thread.yield();
}
});

thread1.start();
}
}

2. 活锁问题

public class LivelockExample {

// ❌ 活锁:两个线程都在互相让步,但都无法执行
public void livelockExample() {
final Object lock1 = new Object();
final Object lock2 = new Object();

Thread thread1 = new Thread(() -> {
while (true) {
synchronized (lock1) {
if (!Thread.holdsLock(lock2)) {
System.out.println("Thread 1: 释放lock1,等待lock2");
Thread.yield(); // 让步给其他线程
continue;
}
System.out.println("Thread 1: 执行工作");
break;
}
}
});

Thread thread2 = new Thread(() -> {
while (true) {
synchronized (lock2) {
if (!Thread.holdsLock(lock1)) {
System.out.println("Thread 2: 释放lock2,等待lock1");
Thread.yield(); // 让步给其他线程
continue;
}
System.out.println("Thread 2: 执行工作");
break;
}
}
});

thread1.start();
thread2.start();
}
}

3. 线程安全问题

public class ThreadSafetyIssues {

// ❌ 非线程安全:SimpleDateFormat
private static final SimpleDateFormat unsafeDateFormat = new SimpleDateFormat("yyyy-MM-dd");

// ✅ 线程安全解决方案
private static final ThreadLocal<SimpleDateFormat> safeDateFormat =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

// ❌ 非线程安全:复合操作
private final List<String> list = new ArrayList<>();

public void unsafeOperation() {
// 检查-然后-操作 不是原子性的
if (!list.contains("key")) { // 步骤1
list.add("key"); // 步骤2:可能被其他线程插入
}
}

// ✅ 线程安全:使用并发集合或同步
public void safeOperation() {
// 方案1:使用并发集合
Set<String> concurrentSet = new ConcurrentHashMap<String, Boolean>().keySet(true);
concurrentSet.add("key");

// 方案2:同步块
synchronized (list) {
if (!list.contains("key")) {
list.add("key");
}
}

// 方案3:使用原子操作
list.addIfAbsent("key");
}

// ❌ 内存泄漏:ThreadLocal未清理
public void threadLocalLeak() {
ThreadLocal<byte[]> threadLocal = new ThreadLocal<>();
threadLocal.set(new byte[1024 * 1024]); // 1MB内存

// 忘记调用threadLocal.remove()会导致内存泄漏
}

// ✅ 正确使用ThreadLocal
public void correctThreadLocalUsage() {
ThreadLocal<byte[]> threadLocal = new ThreadLocal<>();
try {
threadLocal.set(new byte[1024 * 1024]);
// 使用数据
} finally {
threadLocal.remove(); // 必须清理
}
}
}

🚀 性能调优指南

1. 线程池调优策略

public class ThreadPoolTuning {

// CPU密集型任务线程池
public ExecutorService cpuIntensivePool() {
int coreCount = Runtime.getRuntime().availableProcessors();
return new ThreadPoolExecutor(
coreCount, // 核心线程数 = CPU核心数
coreCount, // 最大线程数 = CPU核心数
0L, TimeUnit.SECONDS, // 无空闲时间
new LinkedBlockingQueue<>(100) // 适当的队列大小
);
}

// I/O密集型任务线程池
public ExecutorService ioIntensivePool() {
int coreCount = Runtime.getRuntime().availableProcessors();
return new ThreadPoolExecutor(
coreCount * 2, // 核心线程数 = CPU核心数 * 2
coreCount * 4, // 最大线程数 = CPU核心数 * 4
60L, TimeUnit.SECONDS, // 适当的空闲时间
new LinkedBlockingQueue<>(1000) // 较大的队列
);
}

// 动态调整线程池大小
public ThreadPoolExecutor dynamicThreadPool() {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, 20, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100)
);

// 根据系统负载动态调整
ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
monitor.scheduleAtFixedRate(() -> {
int activeThreads = executor.getActiveCount();
int poolSize = executor.getPoolSize();
double cpuUsage = getCpuUsage();

if (cpuUsage > 0.8 && poolSize < executor.getMaximumPoolSize()) {
// CPU使用率高,增加线程数
executor.setCorePoolSize(Math.min(poolSize + 1, executor.getMaximumPoolSize()));
} else if (cpuUsage < 0.3 && activeThreads < poolSize / 2) {
// CPU使用率低,减少线程数
executor.setCorePoolSize(Math.max(poolSize - 1, executor.getCorePoolSize()));
}
}, 1, 1, TimeUnit.MINUTES);

return executor;
}

private double getCpuUsage() {
// 实现CPU使用率监控
return 0.5; // 示例值
}
}

2. 并发性能监控

public class ConcurrencyMonitor {

// 线程池监控指标
public static class ThreadPoolMetrics {
private final AtomicInteger totalTasks = new AtomicInteger(0);
private final AtomicInteger completedTasks = new AtomicInteger(0);
private final AtomicInteger failedTasks = new AtomicInteger(0);

public void recordTaskSubmission() {
totalTasks.incrementAndGet();
}

public void recordTaskCompletion() {
completedTasks.incrementAndGet();
}

public void recordTaskFailure() {
failedTasks.incrementAndGet();
}

public double getCompletionRate() {
int total = totalTasks.get();
return total == 0 ? 0.0 : (double) completedTasks.get() / total;
}

public void printMetrics() {
System.out.printf("总任务: %d, 已完成: %d, 失败: %d, 完成率: %.2f%%\n",
totalTasks.get(), completedTasks.get(), failedTasks.get(), getCompletionRate() * 100);
}
}

// 监控包装器
public static class MonitoredThreadPoolExecutor extends ThreadPoolExecutor {
private final ThreadPoolMetrics metrics = new ThreadPoolMetrics();

public MonitoredThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}

@Override
public void execute(Runnable command) {
metrics.recordTaskSubmission();
super.execute(new MonitoredRunnable(command, metrics));
}

public ThreadPoolMetrics getMetrics() {
return metrics;
}

private static class MonitoredRunnable implements Runnable {
private final Runnable delegate;
private final ThreadPoolMetrics metrics;

public MonitoredRunnable(Runnable delegate, ThreadPoolMetrics metrics) {
this.delegate = delegate;
this.metrics = metrics;
}

@Override
public void run() {
try {
delegate.run();
metrics.recordTaskCompletion();
} catch (Exception e) {
metrics.recordTaskFailure();
throw e;
}
}
}
}
}

📚 学习路径建议

初学者路径(2-3周)

  1. 线程基础:理解Thread、Runnable、生命周期
  2. synchronized:掌握对象锁和类锁的使用
  3. volatile关键字:理解内存可见性
  4. 基础并发工具:CountDownLatch、CyclicBarrier

进阶路径(3-4周)

  1. JMM内存模型:深入理解happens-before
  2. Lock接口:ReentrantLock、ReadWriteLock
  3. 线程池:ThreadPoolExecutor参数调优
  4. 并发集合:ConcurrentHashMap、BlockingQueue

专家路径(4-6周)

  1. AQS原理:自定义同步器实现
  2. 原子操作:Atomic类底层原理
  3. ForkJoinPool:并行计算框架
  4. 性能调优:并发程序性能优化

💎 核心要点总结

必须掌握的核心概念

  • 三大特性:原子性、可见性、有序性
  • 内存模型:JMM和happens-before原则
  • 锁机制:synchronized优化、Lock接口
  • 并发工具:JUC工具类的使用场景
  • 线程池:ThreadPoolExecutor参数和调优

实战应用关键点

  • 选择合适的并发级别:避免过度并发导致性能下降
  • 正确处理异常:并发环境下的异常传播
  • 资源管理:ThreadLocal的正确使用和清理
  • 性能监控:线程池和并发程序的性能指标
  • 死锁预防:锁的获取顺序和超时机制

面试准备重点

  • JMM原理:内存可见性和指令重排
  • synchronized优化:偏向锁、轻量级锁、重量级锁
  • 线程池参数:corePoolSize、maximumPoolSize、拒绝策略
  • 并发容器:ConcurrentHashMap分段锁、CopyOnWrite机制
  • 原子操作:CAS原理和ABA问题

💡 学习建议:并发编程需要理论与实践相结合,建议每个知识点都通过编写实际代码来验证和理解。注意观察程序运行时的并发行为,使用JProfiler、VisualVM等工具分析性能瓶颈。

接下来建议学习顺序:

  1. 线程基础 - 理解线程创建和生命周期
  2. synchronized关键字详解 - 掌握同步机制
  3. volatile关键字详解 - 理解内存可见性
  4. Java内存模型 - 深入理解JMM
  5. 线程池深度解析 - 掌握任务调度
  6. 原子操作详解 - 无锁编程技术
  7. 锁机制详解 - 高级同步工具