在 synchronized
中可以使用 wait
和 notify
来实现线程在条件不满足时等待,条件满足时被唤醒。
在 ReentrantLock
中使用 Condition
对象来实现 wait
和 notify
对应的功能。
这里将 6.wait 和 notify.md 里的 TaskQueue
使用 ReentrantLock
和 Condition
来实现一遍:
class TaskQueue {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private Queue<String> queue = new LinkedList<>();
public void addTask(String s) {
lock.lock();
try {
queue.add(s);
condition.signalAll(); // singnalAll -> notifyAll
} finally {
lock.unlock();
}
}
public String getTask() {
lock.lock();
try {
while (queue.isEmpty()) {
condition.await(); // await -> wait
}
return queue.remove();
} finally {
lock.unlock();
}
}
}
使用 Condition
时,引用的 Condition
对象必须从 Lock
实例的 newCondition()
返回,这样才能获得一个绑定了 Lock
实例的 Condition
实例。
在 Condition
中使用等待和唤醒与 synchronized
的函数差异:
await()
->wait()
, 会释放当前锁,进入等待状态。single()
->notify()
, 会唤醒某个等待线程。singleAll()
->notifyAll()
, 会唤醒所有等待线程。
与 Reentrant
的 tryLock()
类似,await()
可以等待指定时间后,如果没有其他线程通过 single()
和 singleAll()
唤醒,它会自己醒来。
if (condition.await(1, TimeUnit.SECOND)) { // 等待时长为 1 秒
// 被其他线程唤醒
} else {
// 指定时间内没有被其他线程唤醒
}
小结
Condition
可以替代 wait
和 notify
;Condition
对象必须从 Lock
对象获取。