高 基础
线程间通信方式#
一句话答案#
Java 线程通信方式:volatile/synchronized(共享内存)、wait/notify、Lock/Condition、BlockingQueue、CompletableFuture。
核心要点
主要通信方式:
- volatile 变量:一个线程写,另一个线程读(可见性)
- synchronized + wait/notify:经典的等待-通知机制
- Lock + Condition:更灵活,支持多个等待队列
- BlockingQueue:生产者-消费者模式(推荐)
- CountDownLatch:一组线程等待另一组完成
- CyclicBarrier:一组线程互相等待到齐
- Semaphore:控制并发访问资源的线程数
- CompletableFuture:异步编排,线程间传递结果
常见场景选择:
| 场景 | 推荐方式 |
|---|---|
| 生产者-消费者 | BlockingQueue |
| 多线程协调 | CountDownLatch / CyclicBarrier |
| 异步结果 | CompletableFuture |
| 简单标志位 | volatile |
面试回答(2分钟版)
Java 线程间通信方式可以从低级到高级分几个层次来理解。最基础的是通过共享变量通信,volatile 保证可见性,一个线程写另一个线程能立即读到最新值,适合简单的标志位场景。第二层是 synchronized 配合 wait 和 notify 的经典等待通知机制,wait 会释放锁并进入等待队列,notify 唤醒后重新竞争锁,但缺点是只有一个等待队列不够灵活。第三层是 Lock 配合 Condition,支持多个等待队列,可以精确唤醒特定条件上等待的线程。第四层是更高级的并发工具:BlockingQueue 是生产者消费者场景的首选,自动处理阻塞和唤醒;CountDownLatch 和 CyclicBarrier 用于多线程协调同步;CompletableFuture 用于异步编排和线程间传递结果。实际开发中推荐优先使用高层工具,避免直接操作底层的 wait 和 notify,因为高层工具封装了复杂的同步逻辑,不容易出错。
追问与易错
追问方向:
- “生产者消费者最推荐用什么?”→ BlockingQueue,put/take 自动阻塞唤醒,不用手写 wait/notify,LinkedBlockingQueue 和 ArrayBlockingQueue 是最常用实现
- “wait/notify 有什么缺陷?”→ 只有一个等待队列无法精确唤醒、必须在 synchronized 中使用、容易出现 lost wake-up 和虚假唤醒问题,编码复杂易出错
- “CompletableFuture 和 Future 的区别?”→ Future.get() 阻塞等待且无法组合多个异步任务;CompletableFuture 支持非阻塞回调链(thenApply/thenCompose)、多任务组合(allOf/anyOf)和异常处理(exceptionally/handle)
易错点:
- ❌ 用共享变量轮询代替 wait/notify——浪费 CPU
- ❌ volatile 就能实现通信——只适合简单标志位