Condition 接口
Condition 接口
Condition将 Object 监视方法(wait、notify和notifyAll)分解为不同的对象,通过将它们与任意Lock实现的使用结合起来,实现每个对象具有多个等待集的效果。当Lock取代 synchronized 方法和语句的使用时,Condition取代对象监视方法的使用。
Conditions(也称为条件队列或条件变量)为一个线程提供了一种暂停执行(“等待”)的方法,直到另一个线程通知某个状态条件现在可能为 真。由于对共享状态信息的访问发生在不同的线程中,因此必须对其进行保护,因此某种形式的锁与条件相关联。等待条件提供的关键属性是它原子地释放相关的锁并挂起当前线程,就像Object.wait一样。
Condition实例本质上绑定到一个锁。要获取特定Lock实例的Condition实例,请使用它的newCondition()方法。
举个例子,假设我们有一个支持put和take方法的有界缓冲区。如果在一个空缓冲区上尝试了一个取,那么线程将阻塞,直到有一个项可用;如果在一个满缓冲区上试图执行put操作,那么线程将阻塞,直到有可用的空间。我们希望在单独的等待集中保持等待put线程和take线程,以便在缓冲区中有项或空间可用时,我们可以使用只通知单个线程的优化方法。这可以通过使用两个Condition实例来实现。
Java版本: 1.8.0_341
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
Condition接口
package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.Date;
/**
* Condition实例本质上绑定到一个锁。要获取特定Lock实例的Condition实例,请使用它的newCondition()方法。
*/
public interface Condition {
/**
* 导致当前线程等待,直到收到信号或被中断。
*/
void await() throws InterruptedException;
/**
* 导致当前线程等待,直到收到信号。
*/
void awaitUninterruptibly();
/**
* 导致当前线程等待,直到发出信号或中断,或指定的等待时间结束。
*/
long awaitNanos(long nanosTimeout) throws InterruptedException;
/**
* 导致当前线程等待,直到发出信号或中断,或指定的等待时间结束。
*/
boolean await(long time, TimeUnit unit) throws InterruptedException;
/**
* 导致当前线程等待,直到收到信号或中断,或超过指定的截止日期。
*/
boolean awaitUntil(Date deadline) throws InterruptedException;
/**
* 唤醒一个等待的线程。
*/
void signal();
/**
* 唤醒所有等待的线程。
*/
void signalAll();
}