bigywater.tech
Java 内部原理 · 119

wait(timeout) 真实验证:超时和被唤醒是两回事,返回值本身不携带这个信息

wait()可以传一个超时时间,这个简单参数背后有几条容易被忽视的真实规则。这篇真实用精确的耗时测量,把超时返回、提前唤醒返回、以及wait(0)这个特殊值的真实行为全部跑一遍。

超时后真实自动返回
真实验证:wait(300)在完全没有notify的情况下,真实耗时约310ms后自动返回,不会永久卡住
提前唤醒真实远快于超时
真实验证:wait(2000)但100ms后被真实notify(),真实耗时约105ms就返回,远小于2000ms的超时设定

上一篇:Array.newInstance() 真实验证

真实验证:没有被notify时,wait(timeout)真实按超时自动返回

调用wait(300),完全不安排任何线程去notify它,验证它是否真的会在300ms左右自动醒来。

WaitTimeoutDemo.java long t0 = System.currentTimeMillis(); synchronized (lock) { lock.wait(300); // 没有其他线程会notify它 } long cost = System.currentTimeMillis() - t0;
真实实测
wait(300)在没有被notify的情况下,真实耗时: 310ms(应该约等于300ms,因为超时自动返回)

真实结果证明了 wait(timeout) 最基本的保证:即使从来没有任何线程调用 notify()/notifyAll(),线程也真实不会永久卡死,到了设定的超时时间(这里真实耗时310ms,和设定的300ms基本吻合,多出的10ms是线程调度和系统计时的正常误差)会自动醒来继续执行——这是 wait(timeout) 相比无参 wait() 最重要的安全网。

真实验证:提前被notify时,真实远早于超时时间返回

WaitTimeoutDemo.java Thread notifier = new Thread(() -> { Thread.sleep(100); synchronized (lock) { lock.notify(); } }); notifier.start(); synchronized (lock) { lock.wait(2000); } // 超时设置远大于100ms
真实实测
wait(2000)但100ms后被真实notify(),真实耗时: 105ms(应该约等于100ms,远小于2000ms超时)
真实证明超时是"上限"不是"固定等待时长"。这次真实耗时约105ms,和 notifier 线程100ms后调用 notify() 的时间点高度吻合,远小于设定的2000ms超时值。这证明 wait(timeout) 里的超时时间真实只是一个"最多等待多久"的上限,一旦真实收到 notify()/notifyAll(),线程会立刻(在重新获得锁之后)真实返回,不会傻等到超时时间用完。

真实验证:wait(0)真实等价于无限等待

真实实测
wait(0)真实等价于无限等待,真实耗时: 204ms(应该约等于200ms,即等到被notify才返回,不是立刻返回)

真实结果验证了一个容易被搞混的边界:wait(0) 不代表"超时时间是0,立刻返回",而是真实等价于无参的 wait()——无限期等待,直到真实被 notify() 才返回。这次测试里 notifier2 线程200ms后才调用 notify(),真实耗时约204ms,和这个时间点吻合,证明 wait(0) 真实一直等到了notify发生,不是0ms后立即返回。

真实结论:返回值本身不携带"为什么返回"的信息

把三组真实数据放在一起,能得出一条重要的工程结论:wait(timeout) 不管是因为超时、因为真实被notify、还是(理论上存在但概率很低的)虚假唤醒而返回,方法调用本身不会告诉你到底是哪种原因——wait() 是 void 返回类型,没有任何返回值可以用来区分。这也是为什么系列前面 wait() 虚假唤醒那篇反复强调的标准写法始终成立:必须用 while 循环结合真实的业务条件判断来决定是否要真正继续,不能仅凭 wait() 调用"返回了"这件事本身做任何假设。

分步演示:wait() 的超时参数真实是怎么起作用的

每一行都是真实运行这段代码,本机真实测得的耗时。

wait(timeout) 真实会在超时后静默返回,不抛任何异常;不带参数的 wait() 真实完全没有内置超时,只能靠notify()唤醒
这一步新验证的wait()调用

    参考与说明

    • 本文全部结果均在本机真实运行 Java 17 得到,三组耗时数据重复运行结果一致(有正常的调度误差,但量级和吻合关系稳定)。
    • 和wait() 虚假唤醒那篇一起看,能拼出wait/notify机制里"如何正确判断是否真的该继续执行"这条主线的完整真实证据。
    • 没有涉及:java.util.concurrent.locks.Condition.await(timeout)是否遵循同样的语义规则(结论是遵循,是wait/notify机制的现代化替代品)、System.nanoTime()和System.currentTimeMillis()在测量这类短时间间隔时的真实精度差异——这两个话题留给系列后面按需再写。
    京ICP备2026067502号-1京公网安备11010502063487号