方法收益如何运作?

时间:2011-03-01 16:03:18

标签: java multithreading yield

在javadoc中有说产量方法

  

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

Katherine Sierra和Bert Bates的SCJP书说明了

  

yield()应该做的是   使当前运行的线程返回runnable以允许其他线程   获得轮到他们的优先权。

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

7 个答案:

答案 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)

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

  1. 此主题结束
  2. 此线程执行一些阻塞操作,如object.wait()Thread.sleep,等待某些IO操作完成,等待某个对象监视器或类似操作。
  3. 此主题调用Thread.yield()
  4. 在每种情况下,线程调度程序然后选择另一个要执行的线程。因此,要成为 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
}