第4章 并发编程核心原理与实战
本章聚焦并发编程核心原理与实战,这是Java技术专家面试的高频考点。面试官通常从理论基础、机制对比、工程实践、性能调优四个维度层层深入。掌握系统化的回答框架,能够在面试中从原理到实战全方位展示技术深度。
面试问答实战卡片
基于上述回答框架,以下是三个并发编程高频面试题的实战演练,涵盖线程池、锁机制和volatile核心考点。
Q1:请详细说明线程池的核心参数及其工作原理,如何合理配置线程池?
面试官考察点:对线程池原理的掌握深度,参数配置的实际经验,能否结合业务场景给出合理方案,以及对底层源码的理解程度。
回答框架:参数说明 → 工作流程 → 配置策略 → 实战经验
简短示例回答:线程池核心参数包括corePoolSize、maxPoolSize、keepAliveTime、workQueue、ThreadFactory和RejectedExecutionHandler。工作流程:核心线程执行→任务队列排队→创建新线程至maxPoolSize→触发拒绝策略。配置需区分CPU密集(核心数+1)和IO密集(核心数×2)场景,避免资源耗尽。
可能追问:① 拒绝策略有哪些?分别适用什么场景?② 如何动态调整线程池参数?③ 线程池提交任务时submit和execute的区别?
Executors创建默认线程池(如newFixedThreadPool使用无界队列导致OOM),务必使用ThreadPoolExecutor手动配置,并设置合理的拒绝策略和监控告警。
Q2:synchronized和ReentrantLock有什么区别?实际项目中如何选择?
面试官考察点:对两种锁机制的底层理解,是否掌握锁升级、AQS等原理,能否根据场景做出合理的技术选型。
回答框架:用法对比 → 底层实现 → 特性差异 → 选择依据
简短示例回答:synchronized是JVM关键字,自动加解锁,基于Monitor对象,支持锁升级(偏向→轻量→重量);ReentrantLock是API实现,需手动加解锁,支持公平锁、可中断等待和多个Condition。竞争激烈时ReentrantLock更灵活,简单同步场景优先用synchronized降低复杂度。
可能追问:① synchronized锁升级的具体过程和触发条件?② ReentrantLock的AQS底层原理?③ Condition的用法和与Object.wait/notify的区别?
finally块中释放锁,防止异常导致死锁;synchronized在JDK 6后性能大幅优化,不要盲目替换为Lock。
Q3:volatile关键字的作用和原理是什么?能否保证原子性?
面试官考察点:对内存可见性和指令重排序的理解,是否掌握内存屏障,能否清晰区分volatile与atomic类的适用边界。
回答框架:作用说明 → 原理剖析 → 原子性讨论 → 适用场景
简短示例回答:volatile保证多线程间的可见性和禁止指令重排序,通过内存屏障实现。每次读从主存加载,写立即刷回主存。但不能保证原子性,复合操作如count++仍需synchronized或Atomic类。适用于状态标记、double-check单例等场景。
可能追问:① 内存屏障有哪些类型(LoadLoad、StoreStore等)?② volatile与AtomicInteger的底层区别?③ 单例double-check中volatile的必要性?
项目案例:高并发IM消息推送系统
以下项目案例可用于回答"请介绍一个你负责的高并发项目"类问题,展示并发编程在真实业务中的落地实践。