在Java中,多线程通信与协作主要通过以下几种核心机制实现,每种方式适用于不同的并发场景:
🔄 一、共享变量+同步控制(基础方式)
// 使用volatile保证可见性
private volatile boolean flag = false;// 线程A
new Thread(() -> {while(!flag); // 等待标志位变化System.out.println("检测到标志位变化");
}).start();// 线程B
new Thread(() -> {try { Thread.sleep(1000); } catch (InterruptedException e) {}flag = true; // 修改共享状态
}).start();
特点
- ✅
volatile
保证变量修改的可见性 - ❌ 需配合
synchronized
保证原子性 - ⚠️ 忙等待(while循环)消耗CPU资源
🤝 二、wait()/notify()机制(经典协作)
Object lock = new Object();// 等待线程
new Thread(() -> {synchronized(lock) {try {lock.wait(); // 释放锁并等待System.out.println("被唤醒");} catch (InterruptedException e) {}}
}).start();// 唤醒线程
new Thread(() -> {synchronized(lock) {lock.notify(); // 唤醒等待线程}
}).start();
关键点
- ✅ 精确控制线程阻塞/唤醒
- ❌ 必须配合
synchronized
使用 - ⚠️
notify()
随机唤醒单个线程,notifyAll()
唤醒所有
📨 三、BlockingQueue(生产者-消费者模式)
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);// 生产者
new Thread(() -> {try {queue.put("数据"); // 阻塞式插入} catch (InterruptedException e) {}
}).start();// 消费者
new Thread(() -> {try {String data = queue.take(); // 阻塞式获取System.out.println("消费:" + data);} catch (InterruptedException e) {}
}).start();
优势
- ✅ 内置线程安全与阻塞控制
- ✅ 支持容量限制(防止内存溢出)
- 📊 常用实现:
ArrayBlockingQueue
、LinkedBlockingQueue
🔐 四、CountDownLatch/CyclicBarrier(同步屏障)
CountDownLatch latch = new CountDownLatch(3);// 工作线程
for (int i = 0; i < 3; i++) {new Thread(() -> {System.out.println("子线程完成");latch.countDown(); // 计数器减1}).start();
}latch.await(); // 主线程等待计数器归零
System.out.println("所有线程执行完毕");
对比
工具 | 特点 | 重用性 |
---|---|---|
CountDownLatch | 一次性使用,等待N个任务完成 | ❌ 不可重用 |
CyclicBarrier | 可重复使用,线程互相等待 | ✅ 可重用 |
✉️ 五、Exchanger(线程间数据交换)
Exchanger<String> exchanger = new Exchanger<>();// 线程A
new Thread(() -> {try {String data = exchanger.exchange("数据A");System.out.println("收到:" + data);} catch (InterruptedException e) {}
}).start();// 线程B
new Thread(() -> {try {String data = exchanger.exchange("数据B");System.out.println("收到:" + data);} catch (InterruptedException e) {}
}).start();
适用场景
- ✅ 两个线程间双向数据交换
- ❌ 不支持多线程组交换
🧠 六、Phaser(灵活阶段同步)
Phaser phaser = new Phaser(3); // 注册3个线程for (int i = 0; i < 3; i++) {new Thread(() -> {System.out.println("阶段1完成");phaser.arriveAndAwaitAdvance(); // 等待所有线程System.out.println("阶段2完成");phaser.arriveAndDeregister(); // 退出注册}).start();
}
高级功能
- ✅ 动态调整参与线程数
- ✅ 支持多阶段同步控制
⚡ 最佳实践建议
- 优先选择高层工具
使用BlockingQueue
、CountDownLatch
等JDK并发工具,避免手动实现wait()/notify()
- 避免死锁
按固定顺序获取多把锁,或使用tryLock()
设置超时 - 虚拟线程优化(Java 21+)
Thread.startVirtualThread(() -> { /* 任务代码 */ });
- 监控工具
使用jstack
或VisualVM分析线程阻塞状态
注意:跨线程通信时务必考虑可见性(volatile/happens-before原则)和原子性(锁/CAS),避免出现竞态条件。