Java Thread.Yield()不暂停当前线程

Java Thread.Yield()不暂停当前线程,java,multithreading,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();

正如我所读到的关于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
公共类MyRunnable实现Runnable{
公共静态void main(字符串[]args){
线程t1=新线程(new MyRunnable());
t1.集合名(“第一”);
t1.start();
线程t2=新线程(new MyRunnable());
t2.设定名称(“第二”);
t2.start();

对于(inti=0;i有两种可能的解释

首先,Thread.yield()只是对线程调度程序的一个提示,并不保证在当前线程继续运行之前会运行任何其他线程,更不用说所有其他线程了。在Javadoc中,“调度程序可以随意忽略此提示”和“很少适合使用此方法”:

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


一般来说,无法预测线程的运行顺序,在编写多线程代码时,不应指望不同线程中处理之间的顺序,除非显式同步线程。

您几乎不应在应用程序中使用文档中所述的:

很少使用这种方法。它可能对调试或测试有用,因为它可能有助于重现由于竞争条件而产生的bug

它不能保证它会做任何事情。如果你想在多线程程序中建立一个排序,考虑更方便的更高级的原语,例如,如果你希望在不同线程中的循环中的五次迭代同步,你可以使用<代码> 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();
        }
    }
}
因此,您可以看到,只有在所有线程中的第一次迭代完成之后,第二次迭代才会开始

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

不,那是个误会

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

我不知道这些天在哪里可以找到这样的系统,除了在太小而不能运行Java的微型微控制器上;但很久以前,协作多任务曾经更为常见

大多数现代环境都实现了抢占式多任务:系统可以随时在线程之间切换,而线程甚至不知道发生了什么

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

但是,如果您希望一个线程执行一些长时间运行的后台计算,并且它不需要进行任何系统调用,那么该怎么办呢?您要做的是在计算的关键点添加一些
yield()
调用,以便给其他线程一个运行的机会

在现代系统上,您不应该期望
Thread.yield()
做任何事情。如果系统负载过重,它可能会将调用线程撞到运行队列的后面,……也可能不会。这取决于库实现者的突发奇想


有一件事它绝对不会做(也从来没有做过),那就是“暂停”线程或“等待”任何事情在调用之前、期间和之后都是可运行的。始终。

它没有说明暂停调用线程。这是您编造的。错误!它没有暂停线程,但它通知系统在调用时将切换该线程(上下文切换到另一个线程),
Inside main
Second
First
First
Second
Inside main
Inside main
First
Second
Second
Inside main
First
First
Second
Inside main