在javadoc中有说产量方法
使当前正在执行的线程对象暂时暂停并允许其他线程执行。
Katherine Sierra和Bert Bates的SCJP书说明了
yield()应该做的是 使当前运行的线程返回runnable以允许其他线程 获得轮到他们的优先权。
那么实际上方法在做什么?
答案 0 :(得分:11)
给定多线程应用程序,yield
将导致当前正在执行的线程暂停执行并设置为等待状态。然后,JVM将开始运行另一个先前处于等待状态的线程。
我相信刚刚产生的同一个线程在技术上可以安排重新开始。
我还没有在野外看到这一点。所以我认为可以避免安全。
详细说明:
在多线程环境中,线程会在JVM的意愿下进行调度和非调度。因此,即使在代码中没有调用yield,当JVM决定它应该时,你的线程可以/将自动屈服于其他线程。这允许多线程在只有一个处理核心的环境中工作。
调用yield只是告诉JVM将当前线程置于等待状态,即使JVM没有进行。
我将尝试说明:
以下是随着时间的推移执行2个线程(假设为1个核心)的非常简化的说明 -
Thread\Time 1 2 3 4 5 6 7 8 9
Thread 1 ----------- ----- -------
Thread 2 ------- ---------- ------
每当您看到'-'
表示线程正在执行时。 ' '
表示线程正在等待。如您所见,一次只能运行一个线程。因此,当1次运行时,另一次等待。要产生的收益是让其他线程有机会在当前运行的线程之前运行。
答案 1 :(得分:2)
线程可能处于准备状态(可运行),阻塞(例如,等待某些io完成)或运行;这对于所有线程实现都是通用的,尽管某些特定实现可能具有更多状态。
Yield会导致线程从运行更改为runnable,并等待调度程序将来再次将其更改为运行。这就是SCJP书中的意思。
对于帖子来说,好像它暂停了一段时间,就像在javadoc中所描述的那样。所以这两个陈述都是正确的,只是用不同的措辞。
答案 2 :(得分:2)
yield()
通常用于等待线程发生某些事情,但不希望阻止使用while(condition){ ...}
之类的CPC周期。 yield()的工作方式因平台而异,取决于线程调度程序,您不应该依赖于它以特定方式运行。
答案 3 :(得分:2)
它起源于合作多任务处理的时间。 基本思想是,处理器只执行一个线程,直到:
object.wait()
或Thread.sleep
,等待某些IO操作完成,等待某个对象监视器或类似操作。Thread.yield()
。在每种情况下,线程调度程序然后选择另一个要执行的线程。因此,要成为 fair 到其他线程,您将在没有任何阻塞操作的较长循环中定期调用yield()
。 (如果没有其他线程准备好运行,则会再次安排相同的线程,因此不会造成很大的性能损失。)
在现代虚拟机中,线程切换可以在任何点上进行,不仅这些列出的线程甚至可以同时执行,因此实际上并不是必需的,并且某些虚拟机可能完全忽略它(类似于System.gc()
。)
答案 4 :(得分:2)
yield()方法用于确保应用程序中的所有相同优先级线程不会导致starvation。对于例如应用程序中有五个线程,所有线程都具有相同的优先级。现在假设一个线程有机会运行,这个线程需要很长时间来完成它的任务,因此其他线程不会有机会运行。所以为了避免这种情况,yield()就可以解救了。
答案 5 :(得分:2)
最终,对yield()
的调用会导致调用这样的os方法,原则上会将任务本身放回运行队列并让下一个任务运行(source):< / p>
/**
* 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;
}
答案 6 :(得分:0)
希望有帮助!
package yield;
public class ThreadYieldApp {
Thread th1 = new Thread("Thread 1") {
public void run() {
for(int i = 0; i <= 10; i++) {
System.out.println("Before Yield - " + Thread.currentThread().getName() + " at index - " + i);
//Currently pauses the thread and checks for other threads of same priority, and passes control to it based on Thread Scheduler pick
Thread.yield();
System.out.println("Currently running - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};
Thread th2 = new Thread("Thread 2") {
public void run() {
for(int i = 0; i <= 10; i++) {
System.out.println("Currently running - " + Thread.currentThread().getName() + " at index - " + i);
}
}
};
public static void main(String[] args) {
ThreadYieldApp threadYieldApp = new ThreadYieldApp();
threadYieldApp.th1.start();
threadYieldApp.th2.start();
}
//Happy coding -- Parthasarathy S
}