Java 面试题

Java多线程与并发编程核心要点

"请讲一下Java多线程和并发编程的核心知识。"

为什么面试官会问这道题

并发编程是Java后端工程师的核心能力之一。字节跳动、阿里巴巴等大厂几乎每轮面试都会涉及多线程问题,因为高并发是互联网系统的常态。能否写出线程安全的代码、正确使用线程池,直接决定了系统的稳定性和性能。

如何回答

  1. 1

    从线程创建方式讲起:继承Thread、实现Runnable、实现Callable(有返回值)、线程池(推荐方式)。

  2. 2

    讲清线程状态:NEW → RUNNABLE → BLOCKED/WAITING/TIMED_WAITING → TERMINATED,以及各状态的转换条件。

  3. 3

    重点讲同步机制:synchronized(对象锁/类锁)、volatile(保证可见性但不保证原子性)、ReentrantLock(可重入锁,支持公平锁和超时获取)。

  4. 4

    解释JMM(Java内存模型):主内存与工作内存、happens-before规则、可见性与有序性保证。

  5. 5

    详细说线程池:ThreadPoolExecutor的七个参数、四种拒绝策略、为什么阿里开发规范禁止使用Executors快捷方式。

参考回答示例

Java多线程创建方式有四种:继承Thread类、实现Runnable接口、实现Callable接口配合FutureTask(可获取返回值)、以及通过线程池提交任务。实际开发中推荐使用线程池。ThreadPoolExecutor有七个核心参数:corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、keepAliveTime(空闲线程存活时间)、unit(时间单位)、workQueue(任务队列)、threadFactory(线程工厂)、handler(拒绝策略)。执行流程是:任务来了先看核心线程是否满,没满就创建核心线程;满了就放入队列;队列满了就创建非核心线程直到达到最大线程数;都满了就执行拒绝策略。阿里规范禁止使用Executors.newFixedThreadPool()是因为它用的LinkedBlockingQueue是无界队列,可能导致OOM。同步方面,synchronized是基于Monitor对象锁实现的,JDK1.6之后做了大量优化:偏向锁→轻量级锁→重量级锁,逐步升级。volatile通过内存屏障保证可见性和禁止指令重排序,但不保证原子性,典型场景是double-checked locking单例模式。ReentrantLock相比synchronized更灵活,支持可中断锁、超时锁、公平锁,底层基于AQS(AbstractQueuedSynchronizer)实现。JMM定义了happens-before规则来保证多线程间的可见性:锁释放先于锁获取、volatile写先于volatile读、线程start先于线程内的操作等。JUC包提供了丰富的并发工具:AtomicInteger基于CAS实现无锁原子操作、CountDownLatch实现等待计数、CyclicBarrier实现多线程同步屏障、Semaphore实现信号量限流。

实用技巧

  • 线程池七个参数及执行流程是高频考点,必须烂熟于心。

  • synchronized锁升级过程(偏向锁→轻量级锁→重量级锁)是面试官爱问的进阶题。

  • 准备好AQS原理的回答——ReentrantLock、CountDownLatch底层都是AQS。

  • 面试中如果记混了拒绝策略名称,即答侠可以实时提供准确信息。

常见问题

synchronized和ReentrantLock的区别?

synchronized是JVM层面实现,自动释放锁;ReentrantLock是API层面,需手动释放(finally块)。ReentrantLock支持公平锁、可中断、超时获取、多个Condition。性能上JDK1.6之后差别不大。

CAS是什么?有什么问题?

Compare-And-Swap,比较并交换,是一种乐观锁机制。问题包括:ABA问题(用AtomicStampedReference解决)、自旋开销大、只能保证单个变量的原子性。

ThreadLocal原理和内存泄漏?

ThreadLocal通过每个线程的ThreadLocalMap存储线程私有变量,key是ThreadLocal的弱引用。内存泄漏原因:key被回收后变成null,但value还被强引用。解决:用完必须调用remove()。

面试时担心忘词?即答侠实时助你

即答侠 AI 实时监听面试对话,自动识别问题并即时生成回答建议——无感辅助,让你从容应对每一道题。

免费试用即答侠