首页 > 解决方案 > 下面的while循环可以运行多次吗?

问题描述

我在Android src 代码中发现了一段很简单但看不懂的代码。以下代码是更大功能的一部分(我认为不需要另一部分来回答我的问题)

timeoutMs = 10000   // timeoutMs is a function parameter but for the example i have initiated it here
 if (timeoutMs > 0) {
      long nowMs = SystemClock.uptimeMillis();
      long deadlineMs = nowMs + timeoutMs;
      while (!isDone() && nowMs < deadlineMs) {
          wait(deadlineMs - nowMs);
          nowMs = SystemClock.uptimeMillis();
     }
 }

似乎 while 循环最多会运行一次(取决于isDone值)。在第二个循环中是否存在条件: nowMs <deadlineMs为真?在我看来,在第二种情况下,它们已经相等。那是对的吗?

标签: javaandroidwhile-loopwait

解决方案


您似乎有点误解:wait(100) 等待 100 毫秒!你会认为它会(它读起来几乎像英语,字面意思是:“Wait 100”),但事实并非如此。这不是等待的目的。Thread.sleep(100)是 java-ese 表示“请等待大约 100 毫秒”。wait(100)是java-ese for:请等到通知到达。但是,尽量不要等待超过 100 毫秒。

让我解释一下:wait(x)是你在一个对象上调用,它不是一个实用方法。你在某事上调用它。在这种情况下,正如您刚刚写wait的那样foo.wait,因此,您正在调用它this;这与this.wait(100). 这意味着两件事: [A] 这段代码必须在一个syncronized(this)块内,否则等待调用将立即抛出异常(为什么?因为wait/notify系统如此规定 - 请参阅这些方法的 javadoc。这些方法在 jlObject 本身中) ,并且至关重要的是 [B],此代码的主要目的是等到另一个线程调用x.notify()or x.notifyAll(),其中解析为与在粘贴代码中x解析为相同的对象标识。this但是,那100部分就像一个限制:尽量不要等待更长的时间。换句话说,如果是notify/notifyAlled ,线程将进入睡眠状态,然后在deadlineMs - nowMs几毫秒或更早之后唤醒。this

您可能/很可能正在考虑Thread.sleep(100),它确实尝试暂停大约 100 毫秒,并且不玩任何中断游戏。没有任何notify部分Thread.sleep,并且您不调用sleep任何特定对象。这是一种静态方法。this如果在中途获得 notify/notifyAll-ed ,您粘贴的代码将在 while 循环中运行不止一次。

- 编辑 -

显然还有一些事情不清楚:

“100毫秒不是最大值吗?”

不。对于初学者来说,CPU 和计算机通常不是那么准确,除非您竭尽全力,并关闭它正在执行的所有其他操作。如果恰好在 100 毫秒后 CPU 忙于处理应用程序更新的后台安装,同时将 HDR 应用到该图片,并将另一个上传到 gdrive,也许就在这一毫秒,没有任何时间运行你的东西,可能在大约 5 毫秒内你要走了,那时它会是 105 毫秒。

此外,wait()意味着锁定 - 如果您没有锁定,呼叫会立即崩溃。wait() 释放锁,在代码继续之前,必须重新获取锁,否则线程无法取消暂停。如果你不走运,这可能需要一年时间:所有其他持有锁的线程必须首先进入不再持有它。这部分不适用于Thread.sleep,这又是一个简单的原因Thread.sleep:“等待 x 毫秒左右”,而 wait() 是一个更复杂的野兽,除了超时之外还涉及通知和锁定获取。

等待(0)是什么意思?无法理解参数 0。

这意味着:等到 notify() 进来。如果必须的话,请永远等待。

Thread.sleep(0)很简单:什么都不做(等待 0 毫秒 - 好的,完成。这很容易)。请记住, 的主要目的wait()等待其他线程运行代码x.notify(),其中 x 是您调用的同一个对象wait()超时是事后的想法。0 表示:没有超时,并且是默认行为(也有一个wait()方法,就是wait(0))。

它可以是任何小于“超时”毫秒的时间。


推荐阅读