文章目录
- 一、Java并发编程体系总览
- 1.1 基础机制
- 1.2 并发工具
- 1.2.1 线程池框架
- 1.2.2 Lock框架
- 1.2.3 原子类
- 1.2.4 并发工具类
- 1.3 并发集合
- 1.4 高级特性
- 二、基础线程机制
- 2.1 线程创建方式
- 2.1.1 方式一:继承 Thread 类
- 2.1.2 方式二: 实现Runnable
- 2.1.3 实现三: 实现 Callable 接口 + Future
- 2.2 创建线程方式对比分析
- 三、线程同步机制
- 3.1 synchronized 关键字
- 3.2 Lock框架
- 3.3 volatile关键字
- 3.4 同步机制对比分析
- 四、线程池框架
- 4.1 Executor框架
- 4.2 Fork/Join框架
- 五、并发集合与工具类
- 六、Java 并发编程最佳实践总结
- 6.1 方案选择指南
- 6.2 实践经验总结
- 6.3 常见陷阱与避免
一、Java并发编程体系总览
1.1 基础机制

1.2 并发工具
1.2.1 线程池框架

1.2.2 Lock框架

1.2.3 原子类

1.2.4 并发工具类

1.3 并发集合

1.4 高级特性

二、基础线程机制
2.1 线程创建方式
2.1.1 方式一:继承 Thread 类
public class CustomThread extends Thread {private final String taskName;public CustomThread(String taskName) {super("CustomThread-" + taskName); this.taskName = taskName;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " 开始执行任务: " + taskName);try {Thread.sleep(1000);System.out.println(Thread.currentThread().getName() + " 完成任务: " + taskName);} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName() + " 被中断");Thread.currentThread().interrupt();}}public static void main(String[] args) {CustomThread thread1 = new CustomThread("Task-1");CustomThread thread2 = new CustomThread("Task-2");thread1.start(); thread2.start();try {thread1.join(); thread2.join();} catch (InterruptedException e) {Thread.currentThread().interrupt();}System.out.println("所有任务执行完成");}
}
2.1.2 方式二: 实现Runnable
public class CustomRunnable implements Runnable {private final String taskName;public CustomRunnable(String taskName) {this.taskName = taskName;}@Overridepublic void run() {System.out.println(Thread.currentThread().getName() + " 执行任务: " + taskName);try {Thread.sleep(800);System.out.println(Thread.currentThread().getName() + " 完成任务: " + taskName);} catch (InterruptedException e) {System.out.println(Thread.currentThread().getName() + " 被中断");Thread.currentThread().interrupt();}}public static void main(String[] args) {Thread thread1 = new Thread(new CustomRunnable("Task-A"), "RunnableThread-1");Thread thread2 = new Thread(new CustomRunnable("Task-B"), "RunnableThread-2");thread1.start();thread2.start();CountDownLatch latch = new CountDownLatch(2);new Thread(() -> {try {thread1.join();latch.countDown();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}).start();new Thread(() -> {try {thread2.join();latch.countDown();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}).start();try {latch.await();System.out.println("所有Runnable任务执行完成");} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}
2.1.3 实现三: 实现 Callable 接口 + Future
public class CustomCallable implements Callable<String> {private final String taskName;private final int executionTime;public CustomCallable(String taskName, int executionTime) {this.taskName = taskName;this.executionTime = executionTime;}@Overridepublic String call() throws Exception {System.out.println(Thread.currentThread().getName() + " 开始执行Callable任务: " + taskName);if (executionTime < 0) {throw new IllegalArgumentException("执行时间不能为负数");}Thread.sleep(executionTime);String result = "任务: " + taskName + " 完成,耗时: " + executionTime + "ms";System.out.println(Thread.currentThread().getName() + " " + result);return result;}public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(3);List<Future<String>> futures = new ArrayList<>();for (int i = 1; i <= 5; i++) {CustomCallable task = new CustomCallable("Task-" + i, i * 200);futures.add(executor.submit(task));}for (int i = 0; i < futures.size(); i++) {try {String result = futures.get(i).get(2, TimeUnit.SECONDS);System.out.println("获取到结果: " + result);} catch (InterruptedException e) {System.out.println("任务被中断");Thread.currentThread().interrupt();} catch (ExecutionException e) {System.out.println("任务执行异常: " + e.getCause().getMessage());} catch (TimeoutException e) {System.out.println("任务超时");}}executor.shutdown();try {if (!executor.awaitTermination(3, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();}}
}
2.2 创建线程方式对比分析
特性 | 继承 Thread | 实现 Runnable | 实现 Callable |
---|
继承限制 | 受单继承限制 | 无限制 | 无限制 |
返回值 | 无 | 无 | 有 |
异常处理 | 只能在run()内处理 | 只能在run()内处理 | 可以抛出异常 |
资源占用 | 每个任务需要新建线程 | 可共享线程 | 可共享线程 |
使用复杂度 | 简单 | 简单 | 较复杂 |
适用场景 | 简单独立任务 | 需要资源共享的任务 | 需要结果和异常处理的任务 |
三、线程同步机制
3.1 synchronized 关键字
public class SynchronizedExample {private int count = 0;private final Object lock = new Object();public synchronized void increment() {count++;}public static synchronized void staticIncrement() {}public void incrementWithBlock() {synchronized (lock) {count++;System.out.println(Thread.currentThread().getName() + " count: " + count);}}public void incrementWithThis() {synchronized (this) {count++;}}public static void main(String[] args) throws InterruptedException {SynchronizedExample example = new SynchronizedExample();Thread[] threads = new Thread[10];for (int i = 0; i < threads.length; i++) {threads[i] = new Thread(() -> {for (int j = 0; j < 1000; j++) {example.incrementWithBlock();}}, "Thread-" + i);}for (Thread thread : threads) {thread.start();}for (Thread thread : threads) {thread.join();}System.out.println("最终结果: " + example.count); }
}

3.2 Lock框架
public class LockExample {private int count = 0;private final ReentrantLock lock = new ReentrantLock(true); private final ReadWriteLock rwLock = new ReentrantReadWriteLock();private final StampedLock stampedLock = new StampedLock();public void incrementWithReentrantLock() {lock.lock(); try {count++;System.out.println(Thread.currentThread().getName() + " 写 count: " + count);} finally {lock.unlock(); }}public boolean tryIncrement() {if (lock.tryLock()) { try {count++;return true;} finally {lock.unlock();}}return false;}public int getCountWithReadWriteLock() {rwLock.readLock().lock(); try {return count;} finally {rwLock.readLock().unlock();}}public int getCountWithStampedLock() {long stamp = stampedLock.tryOptimisticRead(); int currentCount = count;if (!stampedLock.validate(stamp)) { stamp = stampedLock.readLock(); try {currentCount = count;} finally {stampedLock.unlockRead(stamp);}}return currentCount;}public static void main(String[] args) throws InterruptedException {LockExample example = new LockExample();Thread writer = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.incrementWithReentrantLock();try {Thread.sleep(1);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}, "Writer");Thread reader = new Thread(() -> {for (int i = 0; i < 500; i++) {int value = example.getCountWithStampedLock();System.out.println(Thread.currentThread().getName() + " 读 count: " + value);try {Thread.sleep(2);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}, "Reader");writer.start();reader.start();writer.join();reader.join();System.out.println("最终结果: " + example.count);}
}

3.3 volatile关键字
package cn.tcmeta.repeat;import java.util.concurrent.atomic.AtomicInteger;
public class VolatileExample {private volatile boolean running = true; private volatile int count = 0; public void stop() {running = false;System.out.println("停止信号已发送");}public void work() {while (running) {try {Thread.sleep(100);count++; System.out.println(Thread.currentThread().getName() + " 工作中... count: " + count);} catch (InterruptedException e) {Thread.currentThread().interrupt();break;}}System.out.println(Thread.currentThread().getName() + " 停止工作");}private final AtomicInteger atomicCount = new AtomicInteger(0);public void atomicWork() {while (running) {try {Thread.sleep(100);int newValue = atomicCount.incrementAndGet();System.out.println(Thread.currentThread().getName() + " atomic count: " + newValue);} catch (InterruptedException e) {Thread.currentThread().interrupt();break;}}}static void main(String[] args) throws InterruptedException {VolatileExample example = new VolatileExample();Thread worker1 = new Thread(example::work, "Worker-1");Thread worker2 = new Thread(example::atomicWork, "Worker-2");worker1.start();worker2.start();Thread.sleep(3000);example.stop();worker1.join();worker2.join();System.out.println("普通count: " + example.count); System.out.println("原子count: " + example.atomicCount.get()); }
}
Worker-2 atomic count: 23
Worker-1 工作中... count: 23
Worker-1 工作中... count: 24
Worker-2 atomic count: 24
Worker-1 工作中... count: 25
Worker-2 atomic count: 25
Worker-1 工作中... count: 26
Worker-2 atomic count: 26
Worker-1 工作中... count: 27
Worker-2 atomic count: 27
Worker-1 工作中... count: 28
Worker-2 atomic count: 28
Worker-1 工作中... count: 29
Worker-2 atomic count: 29
停止信号已发送
Worker-1 工作中... count: 30
Worker-2 atomic count: 30
Worker-1 停止工作
普通count: 30
原子count: 30
3.4 同步机制对比分析
3.4 同步机制对比分析
特性 | synchronized | ReentrantLock | ReadWriteLock | StampedLock | volatile |
---|
锁类型 | 内置锁 | 显式锁 | 读写锁 | 戳锁 | 变量修饰 |
公平性 | 非公平 | 可选公平 | 可选公平 | 非公平 | 无 |
性能 | 较好 | 更好 | 读多写少场景好 | 最好 | 最佳 |
功能 | 基础 | 丰富 | 读写分离 | 乐观读 | 可见性 |
使用复杂度 | 简单 | 复杂 | 复杂 | 最复杂 | 简单 |
适用场景 | 简单同步 | 复杂同步需求 | 读多写少 | 极高性能需求 | 状态标志 |
四、线程池框架
4.1 Executor框架
package cn.tcmeta.repeat;import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
public class ExecutorFrameworkExample {private final ExecutorService fixedPool = Executors.newFixedThreadPool(4);private final ExecutorService cachedPool = Executors.newCachedThreadPool();private final ExecutorService singlePool = Executors.newSingleThreadExecutor();private final ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(2);private final ThreadPoolExecutor customPool = new ThreadPoolExecutor(4, 8, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy() );static class ComputeTask implements Callable<Long> {private final int number;public ComputeTask(int number) {this.number = number;}@Overridepublic Long call() throws Exception {System.out.println(Thread.currentThread().getName() + " 计算: " + number);long result = 0;for (int i = 1; i <= number; i++) {result += i;Thread.sleep(1); }return result;}}public void demonstratePools() throws InterruptedException, ExecutionException {System.out.println("=== 固定大小线程池 ===");List<Future<Long>> futures = new ArrayList<>();for (int i = 1; i <= 10; i++) {futures.add(fixedPool.submit(new ComputeTask(i * 10)));}for (Future<Long> future : futures) {System.out.println("计算结果: " + future.get());}System.out.println("=== 定时任务线程池 ===");scheduledPool.scheduleAtFixedRate(() -> {System.out.println(Thread.currentThread().getName() + " 定时任务执行: " + new Date());}, 1, 2, TimeUnit.SECONDS); Thread.sleep(10000);shutdownPools();}private void shutdownPools() {fixedPool.shutdown();cachedPool.shutdown();singlePool.shutdown();scheduledPool.shutdown();customPool.shutdown();try {if (!fixedPool.awaitTermination(3, TimeUnit.SECONDS)) {fixedPool.shutdownNow();}} catch (InterruptedException e) {fixedPool.shutdownNow();Thread.currentThread().interrupt();}}static void main(String[] args) {ExecutorFrameworkExample example = new ExecutorFrameworkExample();try {example.demonstratePools();} catch (InterruptedException | ExecutionException e) {e.printStackTrace();Thread.currentThread().interrupt();}}
}
=== 固定大小线程池 ===
pool-1-thread-4 计算: 40
pool-1-thread-1 计算: 10
pool-1-thread-2 计算: 20
pool-1-thread-3 计算: 30
pool-1-thread-1 计算: 50
计算结果: 55
计算结果: 210
pool-1-thread-2 计算: 60
计算结果: 465
pool-1-thread-3 计算: 70
pool-1-thread-4 计算: 80
计算结果: 820
计算结果: 1275
pool-1-thread-1 计算: 90
pool-1-thread-2 计算: 100
计算结果: 1830
计算结果: 2485
计算结果: 3240
计算结果: 4095
计算结果: 5050
=== 定时任务线程池 ===
pool-4-thread-1 定时任务执行: Sat Aug 23 21:02:50 CST 2025
pool-4-thread-1 定时任务执行: Sat Aug 23 21:02:52 CST 2025
pool-4-thread-1 定时任务执行: Sat Aug 23 21:02:54 CST 2025
4.2 Fork/Join框架
package cn.tcmeta.repeat;import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.RecursiveTask;
public class ForkJoinExample {static class SumTask extends RecursiveTask<Long> {private static final int THRESHOLD = 1000; private final int start;private final int end;public SumTask(int start, int end) {this.start = start;this.end = end;}@Overrideprotected Long compute() {if (end - start <= THRESHOLD) {long sum = 0;for (int i = start; i <= end; i++) {sum += i;}return sum;}int middle = (start + end) / 2;SumTask leftTask = new SumTask(start, middle);SumTask rightTask = new SumTask(middle + 1, end);leftTask.fork();rightTask.fork();return leftTask.join() + rightTask.join();}}static class PrintTask extends RecursiveAction {private static final int THRESHOLD = 10;private final int[] array;private final int start;private final int end;public PrintTask(int[] array, int start, int end) {this.array = array;this.start = start;this.end = end;}@Overrideprotected void compute() {if (end - start <= THRESHOLD) {for (int i = start; i < end; i++) {System.out.println(Thread.currentThread().getName() + ": " + array[i]);}} else {int middle = (start + end) / 2;PrintTask leftTask = new PrintTask(array, start, middle);PrintTask rightTask = new PrintTask(array, middle, end);invokeAll(leftTask, rightTask);}}}public static void main(String[] args) {ForkJoinPool pool = new ForkJoinPool();SumTask task = new SumTask(1, 1000000);long result = pool.invoke(task);System.out.println("1到1000000的和: " + result);int[] array = new int[100];for (int i = 0; i < array.length; i++) {array[i] = i;}PrintAction printAction = new PrintAction(array, 0, array.length);pool.invoke(printAction);pool.shutdown();}
}
=== 固定大小线程池 ===
pool-1-thread-4 计算: 40
pool-1-thread-1 计算: 10
pool-1-thread-2 计算: 20
pool-1-thread-3 计算: 30
pool-1-thread-1 计算: 50
计算结果: 55
计算结果: 210
pool-1-thread-2 计算: 60
计算结果: 465
pool-1-thread-3 计算: 70
pool-1-thread-4 计算: 80
计算结果: 820
计算结果: 1275
pool-1-thread-1 计算: 90
pool-1-thread-2 计算: 100
计算结果: 1830
计算结果: 2485
计算结果: 3240
计算结果: 4095
计算结果: 5050
=== 定时任务线程池 ===
pool-4-thread-1 定时任务执行: Sat Aug 23 21:02:50 CST 2025
pool-4-thread-1 定时任务执行: Sat Aug 23 21:02:52 CST 2025
五、并发集合与工具类
5.1 并发集合框架
package cn.tcmeta.repeat;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.LinkedBlockingQueue;
public class ConcurrentCollectionsExample {public static void demonstrateConcurrentCollections() {ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();concurrentMap.putIfAbsent("key1", 1);concurrentMap.putIfAbsent("key1", 2); concurrentMap.compute("key2", (k, v) -> v == null ? 1 : v + 1);CopyOnWriteArrayList<String> copyOnWriteList = new CopyOnWriteArrayList<>();copyOnWriteList.add("item1");copyOnWriteList.add("item2");for (String item : copyOnWriteList) {if (item.equals("item1")) {copyOnWriteList.add("item3"); }}BlockingQueue<String> blockingQueue = new LinkedBlockingQueue<>(10);Thread producer = new Thread(() -> {try {for (int i = 0; i < 20; i++) {String item = "item-" + i;blockingQueue.put(item); System.out.println("生产: " + item);Thread.sleep(100);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});Thread consumer = new Thread(() -> {try {for (int i = 0; i < 20; i++) {String item = blockingQueue.take(); System.out.println("消费: " + item);Thread.sleep(150);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}});producer.start();consumer.start();try {producer.join();consumer.join();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}static void main(String[] args) {demonstrateConcurrentCollections();}
}
5.2 并发工具类
public class ConcurrencyToolsExample {public static void demonstrateTools() throws InterruptedException {CountDownLatch startLatch = new CountDownLatch(1);CountDownLatch endLatch = new CountDownLatch(3);for (int i = 0; i < 3; i++) {new Thread(() -> {try {System.out.println(Thread.currentThread().getName() + " 等待开始");startLatch.await(); System.out.println(Thread.currentThread().getName() + " 开始工作");Thread.sleep(1000);System.out.println(Thread.currentThread().getName() + " 完成工作");endLatch.countDown(); } catch (InterruptedException e) {Thread.currentThread().interrupt();}}).start();}Thread.sleep(1000);System.out.println("准备开始...");startLatch.countDown(); endLatch.await(); System.out.println("所有任务完成");CyclicBarrier barrier = new CyclicBarrier(3, () -> {System.out.println("所有线程到达屏障,执行屏障操作");});for (int i = 0; i < 3; i++) {new Thread(() -> {try {System.out.println(Thread.currentThread().getName() + " 到达屏障");barrier.await(); System.out.println(Thread.currentThread().getName() + " 继续执行");} catch (Exception e) {e.printStackTrace();}}).start();}Semaphore semaphore = new Semaphore(2); for (int i = 0; i < 5; i++) {new Thread(() -> {try {semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " 获得许可,执行中");Thread.sleep(2000);semaphore.release(); System.out.println(Thread.currentThread().getName() + " 释放许可");} catch (InterruptedException e) {Thread.currentThread().interrupt();}}).start();}}public static void main(String[] args) throws InterruptedException {demonstrateTools();}
}
六、Java 并发编程最佳实践总结
6.1 方案选择指南
场景 | 推荐方案 | 原因 |
---|
简单同步 | synchronized | 使用简单,JVM优化 |
复杂锁需求 | ReentrantLock | 功能丰富,灵活性高 |
读多写少 | ReadWriteLock/StampedLock | 提高读并发性能 |
状态标志 | volatile | 轻量级可见性保证 |
任务执行 | Executor框架 | 线程池管理,资源可控 |
计算密集型 | Fork/Join框架 | 自动任务分解,充分利用多核 |
数据共享 | 并发集合 | 线程安全,避免显式同步 |
线程协调 | 并发工具类 | 高级同步原语 |
6.2 实践经验总结
- 优先使用高级抽象:尽量使用Executor、并发集合等高级API,避免直接操作线程
- 合理配置线程池:根据任务类型(CPU密集型/IO密集型)配置合适的线程池参数
- 避免死锁:按固定顺序获取锁,使用tryLock带超时
- 注意资源清理:正确关闭线程池和释放资源
- 使用不可变对象:避免同步需求,提高线程安全性
- 合理使用本地变量:减少共享数据,降低同步需求
- 性能监控:使用JMX等工具监控线程状态和性能指标
6.3 常见陷阱与避免
- 内存可见性:正确使用volatile或同步确保可见性
- 竞态条件:使用原子变量或同步避免竞态条件
- 上下文切换开销:避免创建过多线程,使用线程池
- 死锁:避免嵌套锁,使用定时锁
- 活锁:引入随机性避免重复冲突
- 线程泄漏:确保正确关闭和清理资源
Java并发编程是一个复杂但强大的领域,正确使用并发工具和技术可以显著提高程序性能和响应能力。根据具体需求选择合适的并发方案,并遵循最佳实践,才能构建出高效、可靠的并发应用程序。