Condition接口提供比wait/notify更灵活的线程通信机制,支持多等待队列和精确唤醒。它需与Lock配合使用,通过await()、signal()、signalAll()实现线程等待与通知,适用于生产者-消费者、读写锁等复杂并发场景,避免虚假唤醒应使用while条件判断,且必须在锁内操作,推荐优先使用signalAll()确保唤醒可靠性。

在Java并发编程中,当我们需要协调多个线程的执行顺序,让它们在特定条件下等待或被唤醒时,
Condition
Object
wait()
notify()
notifyAll()
Lock
Condition
ReentrantLock
要使用
Condition
Lock
Lock
newCondition()
Condition
Lock
Condition
Condition
核心方法包括:
立即学习“Java免费学习笔记(深入)”;
await()
Condition
signal()
Condition
signalAll()
Condition
让我们通过一个经典的生产者-消费者模型来理解它:
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionProducerConsumer {
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition(); // 队列不满条件
private final Condition notEmpty = lock.newCondition(); // 队列不空条件
private final Queue<Integer> queue = new LinkedList<>();
private final int CAPACITY = 5;
public void produce(int value) throws InterruptedException {
lock.lock(); // 获取锁
try {
while (queue.size() == CAPACITY) { // 队列满,生产者等待
System.out.println(Thread.currentThread().getName() + ":队列已满,等待消费...");
notFull.await(); // 释放锁并等待
}
queue.offer(value);
System.out.println(Thread.currentThread().getName() + ":生产了 " + value + ",当前队列大小:" + queue.size());
notEmpty.signal(); // 队列不空,通知消费者可以消费了
} finally {
lock.unlock(); // 释放锁
}
}
public int consume() throws InterruptedException {
lock.lock(); // 获取锁
try {
while (queue.isEmpty()) { // 队列空,消费者等待
System.out.println(Thread.currentThread().getName() + ":队列为空,等待生产...");
notEmpty.await(); // 释放锁并等待
}
Integer value = queue.poll();
System.out.println(Thread.currentThread().getName() + ":消费了 " + value + ",当前队列大小:" + queue.size());
notFull.signal(); // 队列不满,通知生产者可以生产了
return value;
} finally {
lock.unlock(); // 释放锁
}
}
public static void main(String[] args) {
ConditionProducerConsumer pc = new ConditionProducerConsumer();
Runnable producerTask = () -> {
try {
for (int i = 0; i < 10; i++) {
Thread.sleep((long) (Math.random() * 100));
pc.produce(i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
};
Runnable consumerTask = () -> {
try {
for (int i = 0; i < 10; i++) {
Thread.sleep((long) (Math.random() * 150));
pc.consume();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
};
new Thread(producerTask, "生产者A").start();
new Thread(producerTask, "生产者B").start();
new Thread(consumerTask, "消费者X").start();
new Thread(consumerTask, "消费者Y").start();
}
}这段代码清晰地展示了如何使用两个
Condition
notFull
notEmpty
Lock
从我的经验来看,
Condition
wait/notify
Object.wait()
notifyAll()
Condition
Condition
notFull
notEmpty
notFull
notEmpty
signal()
notEmpty
wait/notify
另一个关键区别是,
Condition
Lock
ReentrantLock
wait/notify
Object
synchronized
Lock
synchronized
Condition
Lock
我个人觉得,
Condition
多条件等待的生产者-消费者模型: 这就是我们上面代码展示的经典场景。当队列有容量限制时,生产者等待“队列不满”的条件,消费者等待“队列不空”的条件。如果使用
wait/notify
notifyAll()
Condition
notFull.signal()
notEmpty.signal()
读写锁的内部实现: 虽然
ReentrantReadWriteLock
Condition
Condition
线程池的等待队列: 许多高级并发工具的内部实现,例如
ThreadPoolExecutor
BlockingQueue
Condition
任何需要多路复用等待队列的场景: 只要你的并发逻辑中存在多个独立的等待条件,并且你希望只唤醒那些真正满足条件的线程,那么
Condition
wait/notify
在使用
Condition
务必在 while
await()
signalAll()
if
while
while (conditionIsNotMet) {
myCondition.await();
}await()
signal()
signalAll()
wait/notify
IllegalMonitorStateException
Condition
考虑使用 signalAll()
signal()
signal()
signalAll()
signalAll()
为不同的等待条件创建独立的 Condition
Condition
signal()
Condition
Condition
notifyAll()
处理中断:
await()
InterruptedException
Thread.currentThread().interrupt()
锁的释放: 确保在
finally
lock.unlock()
Lock
Condition
以上就是Java中使用Condition实现线程通信的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号