发布于2026-07-10 阅读(0)
扫一扫,手机访问
Condition 不是线程池调度器,而是与 ReentrantLock 配合实现任务内精细等待/唤醒的协作工具;它不参与线程池的任务分发,仅用于任务执行过程中基于条件的挂起与唤醒,需配合锁使用且不影响其他任务调度。

说实话,很多开发者刚接触 Condition 时,容易把它和线程池的调度机制混为一谈。其实 Condition 是 java.util.concurrent.locks 包的一员,专门与 ReentrantLock 搭档,干的是“精细等待/唤醒”的细活。而线程池(比如 ThreadPoolExecutor)的任务调度,靠的是内部队列、工作线程和拒绝策略那套体系。两者分工清清楚楚,但在特定场景下——比如线程池任务里需要自定义阻塞等待逻辑——它们可以配合使用。
线程池的职责是“把任务分发给空闲线程执行”,而 Condition 解决的是“某个任务执行过程中,如何让当前线程暂停并等待某个条件成立”。举个例子:一个提交到线程池的任务,需要等待外部信号(比如资源就绪、数据到达)才能继续执行。这时在任务代码里用 Lock + Condition 实现挂起与唤醒,远比让线程池反复轮询或直接阻塞整个工作线程要优雅。
await() 会让当前线程释放锁并进入等待状态,不占用 CPU,也不影响线程池中其他任务执行。signal() 或 signalAll() 由其他线程(可能是另一个任务、主线程或定时器)调用,唤醒等待中的任务线程。ReentrantLock 才能使用,不能搭配 synchronized 或线程池默认锁。假设你有一个线程池,提交了两类任务:一类生产数据(ProducerTask),一类消费数据(ConsumerTask)。ConsumerTask 不能立即执行,得等 ProducerTask 写入共享缓冲区后才开始处理。这时可以在共享资源上定义 Lock 和 Condition:
class SharedBuffer {
private final ReentrantLock lock = new ReentrantLock();
private final Condition dataReady = lock.newCondition();
private volatile boolean hasData = false;
void putData() {
lock.lock();
try {
// 模拟写入
hasData = true;
dataReady.signal(); // 唤醒等待的消费者任务
} finally {
lock.unlock();
}
}
void waitForData() throws InterruptedException {
lock.lock();
try {
while (!hasData) {
dataReady.await(); // 当前任务线程在此挂起,释放锁,不阻塞线程池
}
} finally {
lock.unlock();
}
}
}
ConsumerTask 在 run() 里调用 waitForData(),挂起自身;ProducerTask 完成后调用 putData() 唤醒它。线程池照常调度其他任务,只有这个 ConsumerTask 所在的线程暂时让出执行权。
用 Condition 时,要小心别跟线程池的行为“打架”:
await() 前后长时间持有锁,不然并发性会大打折扣。newFixedThreadPool(1))里大量使用 await,否则容易造成任务堆积和响应延迟。awaitNanos(timeout)),配合重试或取消逻辑,防止任务永久挂起。对于任务调度级的协调,优先考虑更高层的并发工具会更省心:
CompletableFuture 或 Future 链式编排。ScheduledThreadPoolExecutor。BlockingQueue(比如 LinkedBlockingQueue)配合 take()/put(),底层已经封装了类似 Condition 的等待机制。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8