Java 并发性深度解析
Java 并发性深度解析
Java 的并发体系是构建高性能、高吞吐应用的基石,从基础线程模型到 JUC 工具包,提供了完整的并发解决方案。以下是核心内容全景:
一、并发基础模型
组件 | 说明 | 示例 |
---|---|---|
Thread | 基础线程单元 | new Thread(() -> {...}).start() |
Runnable | 无返回值的任务接口 | Executor.execute(runnableTask) |
Callable | 带返回值的任务接口 | Future<Integer> future = executor.submit(callableTask) |
synchronized | 内置锁(对象锁/类锁) | synchronized(lockObj) { ... } |
volatile | 轻量级可见性保证 | private volatile boolean flag; |
关键点:
- 每个 Java 线程对应一个 OS 线程(1:1 模型)
synchronized
优化历程:JDK 1.6 前重量级锁 → 偏向锁/轻量级锁(锁升级)volatile
三大特性:可见性、有序性、禁用指令重排
二、Java 内存模型(JMM)
核心原则:
-
Happens-Before 规则
- 程序顺序规则
- 锁规则(解锁 happens-before 加锁)
volatile
规则- 线程启动规则(
thread.start()
前的修改对线程可见)
-
内存屏障类型
屏障类型 作用 LoadLoad 禁止读-读重排序 StoreStore 禁止写-写重排序 LoadStore 禁止读-写重排序 StoreLoad 禁止写-读重排序(全能屏障)
三、JUC 核心工具(进阶)
-
锁性能对比
锁类型 适用场景 吞吐量 synchronized
简单同步块 中等 ReentrantLock
需要高级特性(超时、公平锁) 高 StampedLock
读多写少 极高 ReadWriteLock
读写分离 高 -
并发容器选型
// 读多写少 Map<String, Data> cache = new ConcurrentHashMap<>(); // 写时复制(监听器列表) List<Listener> listeners = new CopyOnWriteArrayList<>();// 高吞吐队列 BlockingQueue<Log> queue = new LinkedBlockingDeque<>(1000);
四、线程池最佳实践
自定义线程池参数公式:
int coreSize = Runtime.getRuntime().availableProcessors();
int maxSize = coreSize * 2;
int queueCapacity = 1000;new ThreadPoolExecutor(coreSize, maxSize,60L, TimeUnit.SECONDS,new ArrayBlockingQueue<>(queueCapacity),new NamedThreadFactory("app-worker"),new CallerRunsPolicy() // 拒绝策略:调用者运行
);
拒绝策略对比:
策略 | 行为 |
---|---|
AbortPolicy | 抛 RejectedExecutionException(默认) |
CallerRunsPolicy | 由提交任务的线程执行 |
DiscardOldestPolicy | 丢弃队列最老任务 |
DiscardPolicy | 静默丢弃新任务 |
五、异步编程(CompletableFuture)
链式操作示例:
CompletableFuture.supplyAsync(() -> fetchOrder(), ioPool).thenApplyAsync(order -> enrichOrder(order), cpuPool).thenCombineAsync(getUserInfo(order.userId), (order, user) -> mergeData(order, user)).thenAccept(result -> sendNotification(result)).exceptionally(ex -> {log.error("Process failed", ex);return fallbackResult();});
关键操作符:
- 转换:
thenApply()
/thenApplyAsync()
- 消费:
thenAccept()
- 组合:
thenCompose()
(扁平化嵌套 Future) - 并行合并:
thenCombine()
六、并发陷阱与解决方案
问题 | 现象 | 解决方案 |
---|---|---|
死锁 | 线程相互阻塞 | 使用 jstack 分析锁链 |
线程泄漏 | 线程数持续增长 | 监控线程池状态 |
CPU 100% | 空循环/锁竞争激烈 | 用 arthas 定位热点代码 |
伪共享 | 缓存行失效导致性能骤降 | @Contended 填充(Java 8) |
上下文切换开销 | sys 态 CPU 占用高 | 减少锁粒度/无锁算法 |
诊断工具:
jstack
:线程堆栈分析jconsole
:实时监控VisualVM
:性能剖析Arthas
:在线诊断神器
七、现代并发范式
-
响应式编程
Flux.range(1, 100).parallel() // 并行处理.runOn(Schedulers.parallel()).map(i -> i * 2).subscribe();
-
协程(Project Loom)
// 虚拟线程(JDK 21+) Thread vThread = Thread.startVirtualThread(() -> {// 支持百万级并发 });
-
无锁数据结构
// 非阻塞队列 ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>(); queue.offer("data");
并发演进路线图
黄金法则
- 优先用并发容器 → 避免手动同步
- 线程池资源受控 → 禁止无限创建线程
- 锁粒度最小化 → 减小临界区
- 异步优于阻塞 → CompletableFuture/Reactor
- 监控先行 → 生产环境接入 APM 工具(SkyWalking/Prometheus)
性能箴言:
- 无锁 > 乐观锁 > 悲观锁
- 对象复用 > 频繁创建
- 本地计算 > 远程调用
掌握 Java 并发性需要理解从内存模型到高级工具的完整栈,结合性能分析和现代范式,才能构建出高并发、低延迟的下一代系统。