本文目录导读:
在并发编程中,Condition(条件变量)是实现精确唤醒等待线程的核心机制,它解决了 wait/notify 无法指定唤醒特定线程的缺陷。
核心概念
Condition 将锁与等待/通知机制解耦:
- 每个
Condition对象维护一个独立的等待队列 - 线程可以等待特定条件(condition.await())
- 其他线程可以唤醒特定条件上的线程(condition.signal())
Java中的实现:Lock + Condition
基本用法
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BoundedBuffer {
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition(); // 不满条件
private final Condition notEmpty = lock.newCondition(); // 不空条件
private final Object[] items = new Object[100];
private int putIndex, takIndex, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
// 当缓冲区满时,等待"不满"条件
while (count == items.length) {
notFull.await();
}
items[putIndex] = x;
if (++putIndex == items.length) putIndex = 0;
count++;
// 唤醒等待"不空"条件的线程
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
// 当缓冲区空时,等待"不空"条件
while (count == 0) {
notEmpty.await();
}
Object x = items[takIndex];
if (++takIndex == items.length) takIndex = 0;
count--;
// 唤醒等待"不满"条件的线程
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
精确唤醒的工作原理

notFull.await():当前线程释放锁并进入notFull的等待队列notFull.signal():唤醒notFull队列中的一个线程(通常是等待最久的)notFull.signalAll():唤醒notFull队列中的所有线程
典型应用场景
场景1:生产者-消费者模式
public class ProducerConsumerExample {
private final Lock lock = new ReentrantLock();
private final Condition produced = lock.newCondition();
private final Condition consumed = lock.newCondition();
private int product = 0;
private boolean available = false;
public void produce() throws InterruptedException {
lock.lock();
try {
while (available) {
consumed.await(); // 等待产品被消费
}
product++;
System.out.println("生产者生产,当前产品数:" + product);
available = true;
produced.signal(); // 唤醒等待产品的消费者
} finally {
lock.unlock();
}
}
public void consume() throws InterruptedException {
lock.lock();
try {
while (!available) {
produced.await(); // 等待产品被生产
}
System.out.println("消费者消费,当前产品数:" + product);
available = false;
consumed.signal(); // 唤醒等待的生产者
} finally {
lock.unlock();
}
}
}
优势:生产者只唤醒消费者,消费者只唤醒生产者,避免了无意义的线程唤醒。
场景2:多条件精确控制(打印机队列)
class PrinterManager {
private final Lock lock = new ReentrantLock();
private final Condition colorAvailable = lock.newCondition();
private final Condition blackWhiteAvailable = lock.newCondition();
private int colorPrinters = 3;
private int bwPrinters = 5;
public void useColorPrinter(String task) throws InterruptedException {
lock.lock();
try {
while (colorPrinters == 0) {
colorAvailable.await(); // 等待彩色打印机
}
colorPrinters--;
System.out.println(task + " 使用彩色打印机,剩余:" + colorPrinters);
// 打印任务...
} finally {
lock.unlock();
}
}
public void releaseColorPrinter() {
lock.lock();
try {
colorPrinters++;
colorAvailable.signal(); // 只唤醒等待彩色打印机的线程
} finally {
lock.unlock();
}
}
// 黑白打印机方法类似...
}
高级技巧与注意事项
防止条件丢失
// 错误示例
if (!condition) {
condition.await(); // 可能被虚假唤醒
}
// 正确做法:始终在循环中等待
while (!condition) {
condition.await();
}
使用多个Condition实现优先级
class PriorityQueue<T> {
private final Lock lock = new ReentrantLock();
private final Condition highPriority = lock.newCondition();
private final Condition lowPriority = lock.newCondition();
private Queue<T> highQueue = new LinkedList<>();
private Queue<T> lowQueue = new LinkedList<>();
public void highPriorityPut(T item) {
lock.lock();
try {
highQueue.add(item);
highPriority.signal(); // 优先唤醒高优先级消费者
} finally {
lock.unlock();
}
}
public T take() throws InterruptedException {
lock.lock();
try {
while (highQueue.isEmpty() && lowQueue.isEmpty()) {
highPriority.await(); // 等待高优先级
lowPriority.await(); // 等待低优先级
}
if (!highQueue.isEmpty()) {
return highQueue.poll();
}
return lowQueue.poll();
} finally {
lock.unlock();
}
}
}
线程安全地传递条件
class ComplexConditionExample {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
// 使用 volatile 保证可见性
private volatile boolean ready = false;
private volatile String data;
public void producer(String data) {
lock.lock();
try {
this.data = data;
ready = true;
condition.signalAll();
} finally {
lock.unlock();
}
}
public String consumer(long timeout, TimeUnit unit)
throws InterruptedException, TimeoutException {
lock.lock();
try {
while (!ready) {
if (!condition.await(timeout, unit)) {
throw new TimeoutException("等待超时");
}
}
return data;
} finally {
lock.unlock();
}
}
}
性能对比:Condition vs synchronized
| 特性 | synchronized + wait/notify | Lock + Condition |
|---|---|---|
| 等待队列数 | 1个 | 多个(可精确控制) |
| 唤醒精度 | 无法区分条件 | 可唤醒指定条件 |
| 超时控制 | wait(timeout) | await(timeout, unit) |
| 可中断性 | 支持 | 支持 |
| 公平性 | 不可控 | 可配置公平锁 |
| 检查等待队列 | 不支持 | hasWaiters(Condition) |
选择建议:
- 简单场景(1个条件)→
synchronized更简洁 - 复杂场景(多条件/精确控制)→
Lock + Condition
实战:异步任务协调
class AsyncTaskCoordinator {
private final Lock lock = new ReentrantLock();
private final Condition taskCompleted = lock.newCondition();
private volatile int completedCount = 0;
private final int totalTasks;
public AsyncTaskCoordinator(int totalTasks) {
this.totalTasks = totalTasks;
}
public void waitForAll() throws InterruptedException {
lock.lock();
try {
while (completedCount < totalTasks) {
taskCompleted.await();
}
System.out.println("所有任务完成");
} finally {
lock.unlock();
}
}
public void onTaskCompleted() {
lock.lock();
try {
completedCount++;
taskCompleted.signalAll(); // 唤醒主线程
} finally {
lock.unlock();
}
}
// 测试用例
public static void main(String[] args) throws InterruptedException {
AsyncTaskCoordinator coordinator = new AsyncTaskCoordinator(3);
// 启动3个异步任务
for (int i = 0; i < 3; i++) {
int taskId = i;
new Thread(() -> {
try {
Thread.sleep((long)(Math.random() * 1000));
System.out.println("任务 " + taskId + " 完成");
coordinator.onTaskCompleted();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
coordinator.waitForAll();
System.out.println("主线程继续执行");
}
}
Condition 是实现精确唤醒的黄金标准:
- 隔离等待集:每个条件独立的等待队列
- 精确通知:唤醒特定条件的线程
- 提高效率:减少不必要的上下文切换
- 降低复杂度:避免复杂的条件判断
记住核心原则:把相关的线程组织到同一个Condition上,用不同的Condition隔离不同的等待原因。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播