如果我们在具有两个处理器的机器上有两个正在运行的线程,并且在其中一个线程中调用Thread.yield()
,是否就意味着什么都不会发生(调度程序实际上将忽略该请求) ),因为我们有足够的处理器来服务正在运行的线程?
答案 0 :(得分:25)
每当线程调用Thread.yield()
方法时,它都会向线程调度程序提示已准备好暂停其执行。线程调度程序可以随意忽略此提示。
如果有任何线程执行yield方法,则线程调度程序将检查是否有任何可运行(等待执行)线程的优先级与此线程相同或更高。如果处理器发现具有更高或相同优先级的任何线程,则它将切换到新线程。如果没有,则当前线程继续执行。
由于在您的示例中,您有足够的处理器来服务所有线程(它们正在运行,而不是在可运行状态下等待); Thread.yield()
将不执行任何操作,您的线程将继续执行。
Microsoft DOTNet上有关Windows的注释:
此方法等效于使用平台调用来调用本机 Win32 SwitchToThread函数。
收益仅限于执行调用的处理器 线。操作系统不会将执行切换到另一个 处理器,即使该处理器处于空闲状态或正在运行一个 优先级较低。如果没有其他准备就绪的线程 在当前处理器上执行,操作系统不会产生 执行
因此在某些情况下可能会有警告。
答案 1 :(得分:12)
Thread.yield()
已过时。除非您的程序要在实现 cooperative multitasking 的平台上运行,或者在仍使用 green threads 的JVM上运行,否则没有任何意义。调用它。
标准库Javadoc for Thread.yield()
有效地表明yield()
根本不需要做任何事情。
答案 2 :(得分:6)
我一直认为Thread::yield
应该替换为Thread::onSpinWait
(自Java 9开始)-这只是“弱化”收益的一种形式,直到我看到 both < / em>在StampedLock
中:
else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
Thread.yield();
else
Thread.onSpinWait();
return 0L;
所以我不认为它已经过时了。在jdk源内部,它有许多用法,即使是相对较新的ForkJoinPool
也有Thread::yield
用法。
在实践中,我只在忙碌的旋转中使用过Thread::onSpinWait
-因为它的名称至少 alt -何时使用它是非常清楚的。另一方面,收益率不是-因此我无法确定何时以及如何使用它。
我的0.02美元。