Java 多线程与 JUC

返回 面试 · 速查全集 Java常见面试题

并发面试核心:线程状态、锁、JMM、线程池、并发容器。详解 JUCJMM线程池


创建线程

方式说明生产环境
继承 Thread耦合线程与任务不推荐
Runnable任务与线程分离可用
Callable + Future有返回值可用
线程池复用、限流、队列推荐

线程状态

NEW → RUNNABLE → BLOCKED / WAITING / TIMED_WAITING → TERMINATED
状态触发
BLOCKEDsynchronized 监视器
WAITINGwait() / join() / LockSupport.park()
TIMED_WAITINGsleep(n) / wait(n)

synchronized vs ReentrantLock

对比synchronizedReentrantLock
层面JVM 关键字JUC API
释放自动unlock()(finally)
公平锁非公平可选公平
可中断lockInterruptibly
多条件单一 wait/notify多个 Condition
锁升级偏向→轻量→重量无升级概念

synchronized 锁的是对象监视器(实例 this / Class),不是「代码块文字」。


volatile

保证不保证
可见性(写立即对其他线程可见)i++ 原子性
禁止部分指令重排序复合逻辑互斥

典型用途:状态标志、双重检查锁中的 instance(配合 synchronized)。


sleep vs wait

sleepwait
所属ThreadObject
释放锁
唤醒超时notify / notifyAll
使用任意处必须在 synchronized

线程池核心参数

new ThreadPoolExecutor(
    corePoolSize,      // 核心线程
    maximumPoolSize,   // 最大线程
    keepAliveTime,     // 非核心空闲存活
    unit,
    workQueue,         // 任务队列
    threadFactory,
    handler            // 拒绝策略
);

执行顺序:核心未满 → 新建核心线程;满了 → 入队;队满 → 扩到 max;仍满 → 拒绝策略

拒绝策略行为
AbortPolicy抛异常(默认)
CallerRunsPolicy调用者线程执行(降速)
DiscardPolicy丢弃
DiscardOldestPolicy丢最老任务

生产注意:不用 Executors.newFixedThreadPool(无界队列堆积);推荐 有界队列 + 明确 max + CallerRunsPolicy


ThreadLocal

  • 每个线程独立副本,底层 Thread → ThreadLocalMap
  • 线程池场景:finallyremove(),否则复用线程导致脏数据 / 内存泄漏

ConcurrentHashMap

JDK机制
7Segment 分段锁
8+CAS 插入空桶 + synchronized 锁桶头

不允许 null key/value(歧义:不存在 vs 值为 null)。


AQS(了解)

ReentrantLockSemaphoreCountDownLatch 等基于 AQS(状态 + CLH 队列)实现排队获取锁/许可。


常见面试题

Q:如何保证线程安全?
A:不可变对象、synchronized/Lock、原子类(AtomicInteger)、并发容器、ThreadLocal 隔离。

Q:死锁四个条件?
A:互斥、占有且等待、不可抢占、循环等待。线程级见 死锁;DB 见 数据库死锁

Q:CountDownLatch vs CyclicBarrier?
A:Latch 一次性倒数;Barrier 可循环重用,线程互相等到齐。

Q:为什么用线程池而不是 new Thread?
A:降低创建销毁开销、控制最大并发、统一队列与拒绝策略。


相关笔记