Java的Condition::await()是否支持传入谓词/函数作为参数?
解答
Java 1.8 原生Condition接口确实没有提供直接传入谓词函数的await重载方法,但完全可以实现和C++11 condition_variable.wait(mutex, predicate_function)完全等价的功能,不存在能力缺口。
首先要明确:C++11 提供的带谓词参数的wait方法本身只是语法糖,没有特殊的底层能力,它的内部逻辑等价于下面的循环写法,核心是解决多线程场景下的虚假唤醒问题(线程可能在等待条件未满足时就从wait调用中意外返回):
// C++带谓词wait的内部等价逻辑 while (!predicate()) { wait(lock); }
在Java 8中,你只需要按照这个范式编写代码,就能得到完全一致的行为,最常见的有界队列生产场景示例:
Lock lock = new ReentrantLock(); Condition notFull = lock.newCondition(); final int MAX_CAPACITY = 100; Queue queue = new LinkedList(); public void put(Object item) throws InterruptedException { lock.lock(); try { // 循环判断等待条件,和C++传入的predicate作用完全一致 while (queue.size() == MAX_CAPACITY) { notFull.await(); } queue.add(item); } finally { lock.unlock(); } }
如果想要和C++一致的调用体验,完全可以自己封装通用工具方法,直接传入lambda作为判断条件:
// 通用await工具封装 public static void await(Condition condition, BooleanSupplier conditionCheck) throws InterruptedException { while (!conditionCheck.getAsBoolean()) { condition.await(); } } // 调用示例 lock.lock(); try { // 传入lambda谓词,写法和C++几乎无差别 await(notFull, () -> queue.size() < MAX_CAPACITY); queue.add(item); } finally { lock.unlock(); }
注意:不要用单次
if判断替代while循环校验条件,否则遇到虚假唤醒时会出现逻辑错误,这一点不管是Java还是C++的多线程编程都需要遵守。
内容的提问来源于stack exchange,提问作者Troskyvs
相关产品推荐
相关产品推荐

