Java中线程间通信的核心目的,是在线程之间共享数据或协同工作。由于线程之间共享同一个进程的内存空间,因此通信方式主要有两大类:
✅ 一、共享内存方式(主流方式)
原理:多个线程访问共享变量,借助同步机制协调彼此对变量的读写。
常见手段如下:
1. synchronized
关键字(互斥+通信)
class SharedResource {
private int value = 0;
public synchronized void produce() throws InterruptedException {
while (value != 0) {
wait(); // 等待消费者消费
}
value = 1;
System.out.println("Produced");
notify(); // 通知消费者
}
public synchronized void consume() throws InterruptedException {
while (value == 0) {
wait(); // 等待生产者生产
}
value = 0;
System.out.println("Consumed");
notify(); // 通知生产者
}
}
使用
wait()
和notify()
实现线程间通信,需要加锁对象一致,否则抛异常。
2. Lock
+ Condition
比 synchronized
更灵活,支持多个条件队列(显式等待/唤醒)。
Lock lock = new ReentrantLock();
Condition notFull = lock.newCondition();
Condition notEmpty = lock.newCondition();
lock.lock();
try {
while (queue.isEmpty()) {
notEmpty.await(); // 等待数据可消费
}
// 消费数据
notFull.signal(); // 唤醒生产者
} finally {
lock.unlock();
}
3. volatile
关键字(轻量级通信)
volatile
保证变量的可见性和禁止指令重排序,适用于状态标识传递,如:
volatile boolean running = true;
Thread t1 = new Thread(() -> {
while (running) {
// do something
}
});
注意:
volatile
不保证复合操作的原子性,如i++
。
4. 原子类 AtomicXXX
(CAS)
用于实现无锁并发通信,如计数器、状态控制等。
AtomicInteger counter = new AtomicInteger(0);
int newVal = counter.incrementAndGet(); // 原子加1
5. Thread.join()
、Thread.sleep()
、Thread.yield()
这些是时间驱动或线程控制的通信方式:
-
join()
:主线程等待子线程执行完成 -
sleep()
:线程休眠,不释放锁 -
yield()
:让出 CPU,调度器可能让其他线程运行
✅ 二、消息传递方式(线程间不共享变量)
思想:线程之间通过消息队列等机制来传递数据,避免共享变量。
常用方式如下:
1. BlockingQueue
(生产者-消费者模型)
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
Thread producer = new Thread(() -> {
queue.put("task"); // 阻塞直到队列有空间
});
Thread consumer = new Thread(() -> {
String task = queue.take(); // 阻塞直到有数据
});
BlockingQueue
自动实现线程间的等待与唤醒机制,使用简单、线程安全。
2. 并发工具类
工具类 | 通信特性描述 |
---|---|
CountDownLatch | 主线程等待一组线程完成 |
CyclicBarrier | 多个线程互相等待直到到达屏障点 |
Semaphore | 控制线程对资源的访问许可数量 |
Exchanger | 两个线程交换数据(对称通信) |
✅ 三、比较总结
方式 | 模型 | 优点 | 适用场景 |
---|---|---|---|
wait/notify | 共享内存 | 原始方法,控制精细 | 多生产者多消费者 |
Lock/Condition | 共享内存 | 多条件队列,更灵活 | 更复杂同步场景 |
volatile | 标志通信 | 轻量,适合状态通知 | 任务开始/结束标识 |
Atomic | CAS原子操作 | 无锁、高性能 | 计数器、状态位 |
BlockingQueue | 消息传递 | 易用、无锁队列 | 异步生产消费模型 |
CountDownLatch | 通知协调 | 简洁、适合一等多或多等一 | 批处理、服务启动 |
✅ 四、建议使用方式(实战角度)
-
优先使用:
BlockingQueue
、Lock/Condition
、并发工具类 -
wait/notify
只建议用于底层实现,如并发容器或框架 -
单纯标志通信:
volatile
/AtomicBoolean
-
如果要求性能极致,可基于
Unsafe/CAS
自定义通信机制(如 Disruptor)
如需演示某类通信机制的完整代码、原理图、或源码分析(如 BlockingQueue
内部使用的锁机制),可继续提问。