到目前为止,我对wait()和yield()方法的理解是,当线程没有执行任何任务并让CPU执行其他一些线程时,会调用yield()。当一些线程被搁置并且通常用于同步的概念时,使用wait()。但是,我无法理解其功能的差异,我不确定我所理解的是对还是错。有人可以解释它们之间的区别(除了它们存在的包装外)。
答案 0 :(得分:21)
他们都没有做同样的任务 - 等待其他线程可以执行吗?
甚至没有关闭,因为yield()
没有等待。
每个线程可以处于多种不同状态之一:运行意味着线程实际上在CPU上运行, Runnable 意味着什么都没有阻止线程从运行除外,可能是CPU运行的可用性。所有其他状态都可以归为一个名为阻止的类别。被阻塞的线程是一个在可以运行之前等待某事发生的线程。
操作系统定期运行运行线程:每隔一段时间(大多数操作系统每秒10次,每秒100次)每个运行线程的操作系统标记,并说,& #34;轮到你了,跑到跑步队列的后面去#39; (即,将状态从运行更改为可运行)。然后它允许运行队列头部的任何线程使用该CPU(即再次运行)。
当你的程序调用{{1}}时,它会对操作系统说,"我仍然有工作要做,但它可能没有其他一些线程那样重要。这样做。请立即将我发送到运行队列的后面。"如果有一个可用的CPU供线程运行,那么它实际上将继续运行(即,yield()调用将立即返回)。
当你的程序另一方面调用Thread.yield()
时,它会对操作系统说,"阻止我,直到其他线程调用foobar.wait()
。
Yielding首先在非抢占式操作系统上实现,在非抢占式线程库中实现。在只有一个CPU的计算机上,多个线程运行的 only 方式是线程明确相互产生的。
Yielding也对忙碌等待非常有用。这是一个线程在一个紧密的循环中等待某事发生的地方,一遍又一遍地测试相同的条件。如果条件依赖于某个其他线程来做一些工作,那么等待线程每次都会在循环中产生(),以便让其他线程完成它的工作。
现在我们拥有了为我们提供更高级别同步对象的抢占和多处理器系统和库,基本上没有理由为什么应用程序需要再调用foobar.notify()
。
答案 1 :(得分:7)
wait
用于等待条件。在查看方法时,这可能不会引起注意,因为完全取决于您定义它是什么样的条件。但API试图通过要求您拥有您正在等待的对象的监视器来强制您正确使用它,这对于在多线程环境中进行正确的条件检查是必要的。
正确使用wait
看起来像是:
synchronized(object) {
while( ! /* your defined condition */)
object.wait();
/* execute other critical actions if needed */
}
它必须与执行代码的另一个线程配对:
synchronized(object) {
/* make your defined condition true */)
object.notify();
}
相比之下,Thread.yield()
只是一个提示,您的线程可能会在此时释放CPU。它没有指定它是否实际执行任何操作,无论CPU是否已被释放,它都不会影响内存模型的语义。换句话说,它不会与正确访问共享变量所需的其他线程建立任何关系。
例如,访问sharedVariable
(未声明为volatile
)的以下循环可能会永远运行而不会注意到其他线程所做的更新:
while(sharedVariable != expectedValue) Thread.yield();
虽然Thread.yield
可能有助于其他线程运行(它们无论如何都会在大多数系统上运行),但不强制重新从共享中读取sharedVariable
的值记忆。因此,没有其他构造强制执行存储器可见性,例如,将sharedVariable
标记为volatile
,此循环已中断。
答案 2 :(得分:3)
第一个区别是yield()
是Thread
方法,wait()
方法Object
方法继承thread
方法,与所有类一样,在形状中,在后台(使用java doc)
wait()
使当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法。换句话说,此方法的行为就像它只是执行call wait(0)一样。
yield()
向调度程序提示当前线程是否愿意产生其当前对处理器的使用。调度程序可以忽略此提示。
在这里,您可以看到difference和yield()之间的wait()