Java 并发编程面试题 123 道

笔记/Java/面试专栏/Java 并发编程面试题 123 道

整理自 Java 并发编程面试题 123 道(含多章节子题)。精简版多线程题见 多线程面试 59 道

相关学习笔记#

专题笔记
线程基础01 线程基础
生命周期02 生命周期与通信
JMM / volatile03 JMM 与 volatile
synchronized / Lock04 synchronized 与 Lock
Atomic / CAS05 Atomic 与 CAS
线程池06 线程池
工具类07 并发工具类
ThreadLocal08 ThreadLocal
并发容器09 并发容器

目录#


一、基础知识(1–52)#

1. 为什么要使用并发编程?#

提高多核 CPU 利用率;业务拆分并行(如订单减库存);避免单线程 IO 阻塞拖死整体。

2. 多线程应用场景#

下载多线程、连接池、批量发短信、Web 容器多线程处理请求等。

3. 并发编程有什么缺点?#

上下文切换开销、内存占用、竞态与死锁、调试困难;并非总能加速。

4. 并发编程三个必要因素?#

原子性、可见性、有序性。→ JMM

5. Java 如何保证多线程运行安全?#

synchronized/Lock 保原子性;volatile/synchronized/Lock 保可见性;happens-before 保有序性。

6. 并行和并发有什么区别?#

并发:单核交替,逻辑同时;并行:多核真正同时;串行:单线程顺序执行。

7–9. 什么是多线程 / 好处 / 劣势#

多执行流;提高 CPU 利用、防阻塞;代价是内存、调度、同步复杂度。

10. 线程和进程区别#

资源分配 vs 调度单位;独立地址空间 vs 共享堆;切换开销与健壮性不同。→ 线程基础

11. 什么是上下文切换?#

时间片用完,保存当前线程状态、切换另一线程,有 CPU 开销。

12. 守护线程和用户线程区别#

用户线程结束则 JVM 退出;守护线程自动结束。setDaemon(true)

13. 如何查找 CPU 占用最高的线程?#

Linux:toptop -H -p pid → 线程 id 转 16 进制 → jstack pid 对照;或用 JVisualVM。

14–16. 死锁 / 四条件 / 如何避免#

互相等待资源;互斥、占有等待、不可抢占、循环等待。固定加锁顺序、tryLock 超时、缩小锁范围。

17. 创建线程的四种方式#

Thread、Runnable、Callable+Future、线程池。

18. Runnable 和 Callable 区别#

Runnable 无返回值无 checked 异常;Callable 有返回值,可抛异常。

19–20. run() 和 start() / 为何 start 会执行 run#

start 注册到 JVM 调度;run 只是普通方法。→ 线程基础

21–22. Callable 与 Future / FutureTask#

Future 表示异步结果;FutureTask 实现 Runnable+Future,可提交线程池。

23. 线程的状态#

NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。

24–26. 调度算法 / 策略 / Scheduler#

抢占式;时间片轮转;Scheduler 分配 CPU 时间片。

27. 线程同步与调度相关方法#

wait/notify/notifyAll、sleep、yield、join、interrupt 等。

28. sleep() 和 wait() 区别#

sleep 不释放锁;wait 释放监视器并等待 notify。

29. wait 用 if 还是 while?#

while,防伪唤醒。→ 生命周期

30–31. wait/notify 为何在 Object / 为何要在同步块#

锁是对象级;API 要求,否则 IllegalMonitorStateException。

32–34. yield / sleep 与 yield 区别 / 为何是静态#

yield 让出 CPU;sleep 阻塞指定时间;作用于当前线程故静态。

35. 如何停止正在运行的线程?#

协作式 interrupt 或 volatile 标志,不用 stop()。

36. interrupted 和 isInterrupted 区别#

interrupted() 静态,检测并清除中断标志;isInterrupted() 实例,不清除。

37–38. 阻塞式方法 / 如何唤醒阻塞线程#

accept/read/get 等;interrupt 可唤醒 wait/sleep/join,IO 阻塞难以中断。

39. notify 和 notifyAll#

notify 唤醒一个;notifyAll 唤醒全部。

40–41. 两线程共享数据 / 通讯与协作#

共享变量+同步;wait/notify、BlockingQueue、Lock Condition。

42–43. 同步块 vs 同步方法 / 同步与互斥实现#

同步块范围更小更好;synchronized、Lock、volatile(有限)。

44. Monitor 内如何做线程同步#

enter monitor → 执行 → exit;竞争 monitor 所有权。

45. 提交任务时队列已满会怎样?#

未达 max 扩线程;达 max 且队列满则拒绝策略;无界队列则持续排队。→ 线程池

46–47. 线程安全 / Servlet 线程安全吗#

多线程访问共享数据结果正确;Servlet 实例共享,成员变量需防并发,局部变量安全。

48. 线程优先级#

1–10,影响调度概率非绝对;避免依赖优先级保证逻辑。

49. 线程构造方法、静态块被谁调用#

定义该线程的父线程(创建 Thread 对象的线程)。

50. 如何获取线程 dump#

jstack pid、kill -3、JConsole/VisualVM。

51–52. 线程异常 / 线程过多异常#

未捕获则线程终止;OOM、栈溢出、GC 压力。

53. 多线程常用方法(节选)#

start、run、sleep、join、interrupt、currentThread、setDaemon 等。


二、并发理论与同步(1–35)#

1–2. GC 目的 / 线程通信与同步#

回收无用对象;Java 共享内存模型,通信隐式通过主内存完成。

3. Java 内存模型#

线程本地内存与主内存;写 flush、读 load 才可见。→ JMM

4–5. null 引用立即回收吗 / finalize#

不会立即;finalize 在 GC 决定回收时调用一次,不可靠,不推荐依赖。

6–8. 重排序 / 三种重排 / as-if-serial 规则#

编译器、CPU、内存系统重排;单线程结果不变,多线程可能可见性问题。

9. as-if-serial 与 happens-before 区别#

前者保证单线程语义;后者保证正确同步的多线程结果。

10–11. synchronized 关键字 / 项目用法#

修饰方法、静态方法、代码块;勿锁 String 常量池相同对象。

12. 双重检查锁单例#

实例引用必须 volatile,防指令重排看到未初始化对象。

13–14. synchronized 底层 / 可重入原理#

monitor enter/exit;计数器重入。

15–16. 自旋 / synchronized 锁升级#

忙循环尝试获锁;无锁→偏向→轻量→重量。→ synchronized

17–18. 线程 B 如何知道 A 修改变量 / 其他线程能否进其他 synchronized 方法#

volatile/synchronized 可见;实例锁锁整个实例非静态方法,静态锁锁类。

19. synchronized、volatile、CAS 比较#

synchronized 互斥;volatile 可见+有序;CAS 无锁原子更新。

20–21. synchronized 和 Lock / 和 ReentrantLock 区别#

Lock 可 tryLock、公平、多 Condition、需手动 unlock。

22–26. volatile 作用 / 能否 volatile 数组 / vs Atomic / 能否变原子 / vs synchronized#

可见+禁重排;数组元素需 AtomicReferenceArray 等;volatile 不保证 i++。

27. final 不可变对象的帮助#

安全发布后无锁读,简化并发。

28. Lock 相对 synchronized 优势#

尝试锁、超时、中断、读写锁、公平性。

29–31. 乐观悲观锁 / CAS / CAS 问题#

CAS 乐观;ABA、自旋开销、单变量限制。→ Atomic

32–34. 原子类 / 常用类 / Atomic 原理#

AtomicInteger 等;Unsafe CAS 循环。

35. 死锁、活锁、饥饿区别#

多线程 59 道 #19


三、线程池(1–15)#

1–3. 线程池是什么 / 作用 / 优点#

复用线程、控制并发、降低创建销毁开销。

4–5. ThreadPoolExecutor / Executors#

七大参数;Executors 工厂方法,生产建议手动 new ThreadPoolExecutor。

6–8. 四种创建方式 / Executor vs Executors / 区别与特点#

Fixed、Cached、Scheduled、Single;Cached 可能线程爆炸,Fixed 无界队列风险。

9. 线程池状态#

RUNNING → SHUTDOWN → STOP → TIDYING → TERMINATED。

10. submit 和 execute#

submit 返回 Future;execute 无返回值。

11. 线程组为何不推荐#

ThreadGroup API 老旧,异常处理弱;用线程池+命名 ThreadFactory。

12. 饱和策略#

Abort、CallerRuns、Discard、DiscardOldest。

13–14. 自定义线程池 / 执行原理#

显式 core/max/队列/handler;core 未满新建→入队→扩到 max→拒绝。

15. 如何合理分配大小#

CPU 密集 ≈ 核数;IO 密集可 2×核数或按阻塞比例估算。→ 线程池


四、并发容器(1–14)#

1. 常用并发容器#

ConcurrentHashMap、CopyOnWriteArrayList;替代 Vector/Hashtable。

2–4. Vector / vs ArrayList / Hashtable 为何线程安全#

方法 synchronized;Hashtable 全表锁。

5–6. ConcurrentHashMap vs Hashtable / synchronizedMap#

CHM 桶级锁/CAS;Hashtable 全表锁;JDK8 CHM 无 Segment。

7. ConcurrentHashMap 并发度#

JDK7 Segment 数;JDK8 弃用,CAS+synchronized 桶。

8–10. 并发容器实现 / vs 同步集合 / SynchronizedMap vs CHM#

锁分离、写时复制;CHM 迭代弱一致不抛 CME(部分容器)。

11–14. CopyOnWriteArrayList 是什么 / 场景 / 缺点 / 设计思想#

读多写少;写复制数组;写开销大、最终一致。→ 并发容器


五、并发队列(1–6)#

1–2. 并发队列是什么 / vs 并发集合#

FIFO 协作;集合强调共享数据结构。

3–4. 阻塞 vs 非阻塞 / 区别#

BlockingQueue 满/空时阻塞;ConcurrentLinkedQueue CAS 非阻塞。

5. 常用队列介绍#

ArrayBlockingQueue(有界)、LinkedBlockingQueue、SynchronousQueue、DelayQueue、PriorityBlockingQueue 等。

6. SynchronousQueue#

不存储元素,直接交接,线程池 Cached 常用。


六、并发工具类(1–3)#

1. 常用并发工具类#

CountDownLatch(一个等多个)、CyclicBarrier(互相等到齐)、Semaphore(限流)。

2–3. CyclicBarrier 细节 / Semaphore#

Barrier 可重用+ barrierAction;Semaphore acquire/release 控制并发数。

→ 详见 并发工具类


速记对照#

场景选型
共享 MapConcurrentHashMap
读多写少 ListCopyOnWriteArrayList
任务排队BlockingQueue + 线程池
等多任务完成CountDownLatch
限 3 并发Semaphore(3)
线程内上下文ThreadLocal + remove
可见性volatile / synchronized
原子计数AtomicInteger / LongAdder
文章目录

文章目录