Thread.Yield()没有暂停当前线程

时间:2015-09-11 04:13:30

标签: java multithreading

正如我所读到的关于yield()。

它暂停当前线程并执行下一个线程,但为什么它不会暂停第一个线程。

请解释它是如何运作的。

这是我的代码

public class MyRunnable implements Runnable {

   public static void main(String[] args) {
      Thread t1 = new Thread(new MyRunnable());
      t1.setName("First");
      t1.start();
      Thread t2= new Thread(new MyRunnable());
      t2.setName("Second");
      t2.start();

      for(int i=0; i<5; i++) {
          System.out.println("Inside main");
      }
   }

   public void run() {
      for(int i=0; i<5; i++) {
          System.out.println(Thread.currentThread().getName());
          Thread.yield();

      }
   }
}

This is my output

Inside main
Inside main
Inside main
Inside main
Inside main
First
First
First
First
First
Second
Second
Second
Second
Second

我创建了两个线程第一个线程和第二个线程。我想知道使用yield()方法。     因为我读过abt yield()。它暂停当前线程并执行下一个线程。为什么它不会暂停第一个线程.Plz expalin它将如何工作。

3 个答案:

答案 0 :(得分:2)

您应该几乎不要在您的应用程序中使用Thread.yield(),因为文档说:

  

使用此方法很少合适。它可能对调试或测试有用,它可能有助于重现因竞争条件而产生的错误

它不保证它是否会做任何事情。如果要在多线程程序中建立排序,请考虑更方便的高级原语,如CyclicBarrierPhaser。例如,如果要同步不同线程中循环中的五次迭代,可以使用Phaser,如下所示:

import java.util.concurrent.Phaser;

public class MyRunnable implements Runnable {
    Phaser p;

    public MyRunnable(Phaser p) {
        this.p = p;
    }

    public static void main(String[] args) {
        // We have three parties: main thread and two additional threads
        Phaser p = new Phaser(3); 

        Thread t1 = new Thread(new MyRunnable(p));
        t1.setName("First");
        t1.start();
        Thread t2 = new Thread(new MyRunnable(p));
        t2.setName("Second");
        t2.start();

        for (int i = 0; i < 5; i++) {
            System.out.println("Inside main");
            // notify Phaser that phase is finished and wait other parties before continue
            p.arriveAndAwaitAdvance();
        }
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName());
            // notify Phaser that phase is finished and wait other parties before continue
            p.arriveAndAwaitAdvance();
        }
    }
}

典型输出如下:

Inside main
Second
First
First
Second
Inside main
Inside main
First
Second
Second
Inside main
First
First
Second
Inside main

所以你可以看到,只有在所有线程的第一次迭代完成后,第二次迭代才会开始。

答案 1 :(得分:1)

有两种可能的解释。

首先,Thread.yield()只是线程调度程序的提示,并不保证任何其他线程,更不用说所有其他线程,将在当前线程继续之前运行。来自Javadoc,&#34;调度程序可以自由地忽略这个提示&#34;和#34;很少使用这种方法&#34;:

http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#yield()

其次,设置新线程需要大量的系统处理。可能是第二个线程需要足够长的时间来设置允许第一个线程在第二个线程准备好打印之前打印五行。

作为一般规则,无法预测线程的运行顺序,并且在编写多线程代码时,不应指望不同线程中处理之间的任何排序,除非您明确地同步线程。

答案 2 :(得分:0)

  

[Thread.yield() ...]它暂停当前线程并执行下一个线程。

没有。这是一个误解。

Thread.yield()的目的是为在协作式多任务系统中运行的程序中的上下文切换创建机会

我不知道在哪里可以找到像这样的系统,除了可能在微小的微控制器上,这些微控制器太小而无法运行Java;但很久以前,合作多任务处理更为常见。

大多数现代环境实现抢占式多任务处理:系统可以随时在线程之间切换,并且线程甚至不知道它发生了。

在协作式多任务系统中,当当前线程执行系统调用时,系统只能在线程之间切换。

但是,如果你想让一个线程执行一些长时间运行的后台计算,并且它不需要进行任何系统调用,该怎么办?您要做的是在计算中的战略要点添加一些yield()次调用,以便为其他线程提供运行的机会。

在现代系统中,您不应期望Thread.yield()可以做任何事情。也许,如果系统负载很重,它会将调用线程碰到运行队列的后面,......或者可能不会。取决于库实现者的心血来潮。

它绝对不做(而且从未做过)的一件事是“暂停”线程或“等待”任何事情。调用yield()的线程在调用之前,期间和之后都是RUNNABLE。总是