方法收益如何运作?

在javadoc中有说yield方法

使当前正在执行的线程对象暂时暂停并允许其他线程执行。

而Katherine Sierra和Bert Bates的SCJP书也说明了这一点

yield()应该做的是使当前正在运行的线程返回runnable以允许具有相同优先级的其他线程轮到他们。

那么实际上方法在做什么?

给定multithreading应用程序, yield将导致当前正在执行的线程暂停执行并设置为等待状态。 然后,JVM将开始运行之前处于等待状态的另一个线程。

我相信刚刚产生的同一个线程在技术上可以安排重新开始。

而且我还没有在野外看到这一点。 所以我觉得避免安全是可以的。

详细说明:

在multithreading环境中,线程是在JVM的意愿下调度和打开的。 因此,即使在代码中没有调用yield,当JVM决定它应该时,你的线程可以/将自动屈服于其他线程。 这允许multithreading在仅具有一个处理核心的环境中工作。

调用yield只是告诉JVM将当前线程置于等待状态,即使JVM不会。

我将尝试一个例子:
以下是随着时间的推移执行2个线程的非常简化的说明(假设1个核心) –

 Thread\Time 1 2 3 4 5 6 7 8 9 Thread 1 ----------- ----- ------- Thread 2 ------- ---------- ------ 

每当你看到'-'表示线程正在执行时。 A ' '表示线程正在等待。 如您所见,一次只能运行一个线程。 因此,当1次运行时,另一次等待。 要产生的收益是让其他线程有机会在当前运行的线程之前运行。

yield()通常用于等待线程发生某些事情但不想用while(condition){ ...}来阻止CPC周期while(condition){ ...} 。 yield()的工作方式因平台而异,取决于线程调度程序,您不应该依赖于它以特定方式运行。

它源于合作多任务处理的时间。 基本思想是,处理器只执行一个线程,直到:

  1. 这个post结束了
  2. 这个线程执行一些阻塞操作,比如object.wait()Thread.sleep ,等待一些IO操作完成,等待一些对象监视器或类似操作。
  3. 这个线程调用Thread.yield()

在每种情况下,线程调度程序然后选择另一个要执行的线程。 因此,为了公平对待其他线程,您将在没有任何阻塞操作的较长循环中定期调用yield() 。 (如果没有其他线程准备好运行,则会再次安排相同的线程,因此不会造成很大的性能损失。)

在现代VM中,线程切换可以在任何点上发生,不仅这些列出的线程甚至可以同时执行,因此它不是必需的,并且一些VM可能完全忽略它(类似于System.gc() 。)

yield()方法用于确保应用程序中的所有相同优先级线程不会导致饥饿 。 例如,应用程序中存在五个线程,并且所有线程具有相同的优先级。 现在假设一个线程有机会运行,并且这个线程需要很长时间来完成它的任务,因此其他线程将无法运行。 所以为了避免这种情况,yield()就可以解救了。

最终,对yield()的调用导致调用这样的os方法,这原则上会将任务本身放回到运行队列中并让下一个任务运行( 源 ):

  /** * sys_sched_yield - yield the current processor to other threads. * * This function yields the current CPU to other tasks. If there are no * other threads running on this CPU then this function will return. */ SYSCALL_DEFINE0(sched_yield) { /* * lock this runqueue and disable interrupts. */ struct rq *rq = this_rq_lock(); schedstat_inc(rq, yld_count); current->sched_class->yield_task(rq); /* * Since we are going to call schedule() anyway, there's * no need to preempt or enable interrupts: */ __release(rq->lock); spin_release(&rq->lock.dep_map, 1, _THIS_IP_); _raw_spin_unlock(&rq->lock); preempt_enable_no_resched(); schedule(); return 0; } 

线程可以处于准备状态(可运行),阻塞(例如,等待某些io完成)或运行; 这对于所有线程实现都是通用的,尽管某些特定实现可能具有更多状态。

Yield会导致线程从运行更改为可运行,并等待调度程序将来再次将其更改为运行。 这就是SCJP书中的含义。

对于线程来说,它似乎暂停了一段时间,就像在javadoc中描述的那样。 所以这两个陈述都是正确的,只是用不同的措辞。