Java Thread.yield()奇怪的行为

Java Thread.yield()奇怪的行为,java,multithreading,Java,Multithreading,这是我的密码: class MyThread extends Thread{ public void run(){ for (int i = 0; i<=10; i++){ System.out.println("Child Thread"); Thread.yield(); } } } public class TestYield {

这是我的密码:

  class MyThread extends Thread{
    public void run(){
        for (int i = 0; i<=10; i++){
            System.out.println("Child Thread");
            Thread.yield();
            
        }
    }
}
  public class TestYield {
    public static void main(String[] args) {
        MyThread obj = new MyThread();
        obj.start();
        for (int i = 0; i<=10; i++){
            System.out.println("Main Thread");
        }
    }
}
一旦执行计数器切换到第二个线程,必须打印出“子线程”,直到此时我们的输出扩展为:

Main Thread
Main Thread
Main Thread
Main Thread
Main Thread
Main Thread
Child Thread
但在原始输出中,“主线程”首先完成其执行 所以我的问题是:-

为什么第一个sysout(“子线程”)没有在thread.yield()之前执行? 我得到的结果是:

Main Thread
Main Thread
Main Thread
Main Thread
Main Thread
Main Thread
Main Thread
Main Thread
Main Thread
Main Thread
Main Thread
Child Thread
Child Thread
Child Thread
Child Thread
Child Thread
Child Thread
Child Thread
Child Thread
Child Thread
Child Thread
Child Thread
更新: 我的问题现在已经解决了 以下是从Stephen C和 @user15793316

  • 启动一个新线程实际上需要花费大量的时间。 可能是几毫秒

  • 主线程的速度太快,以至于子线程没有被激活 已开始(或完成已开始)-可能在主要市场中出现收益 最终帮助孩子线程获得运行的机会。(及 从10次增加到100次或更多次迭代)

  • 所以我更新了我的代码并添加了line
    Thread.sleep((long)0.1)
    这是我的更新代码:

    public class TestYield {
        public static void main(String[] args) throws InterruptedException {
            MyThread obj = new MyThread();
            obj.start();
            Thread.sleep((long) 0.1);
            for (int i = 0; i<=10; i++){
                System.out.println("Main Thread");
            }
        }
    }
    

    p.S:现在对我来说很奇怪,我是如何得到我想要的,应该是的确切输出的。主线程只执行前3次(:lol!

    1-主线程太快了,以至于子线程还没有启动(或完成启动)-可能主线程中的
    屈服
    最终会帮助子线程获得运行的机会。(并且从
    10
    增加到
    100
    或更多迭代次数)

    2-
    yield
    不保证另一个线程将运行(从:“调度器可以自由忽略此提示”)。由于主线程中没有
    yield
    ,因此不太相关


    3-检查软件包。
    实际上,
    yield
    文档也说明“很少适合使用这种方法。”

    好的,让我们从for
    yield()开始

    “对调度程序的提示,表示当前线程愿意使用处理器。调度程序可以忽略此提示。

    收益率是一种启发式尝试,旨在改善线程之间的相对进度,否则会过度使用CPU。它的使用应与详细的评测和基准测试相结合,以确保它实际具有预期的效果

    使用这种方法很少合适。[…]”

    这并不是说,
    yield()
    对日程安排有可预测的影响。因此,你对可预测行为的期望是没有根据的


    至于在您的示例中实际发生的情况,似乎
    main
    线程在调用子线程的
    run()
    方法之前正在完成其循环

    为什么?可能有两件事:

  • 启动一个新线程实际上需要相当长的时间,可能需要毫秒

  • 根据可用内核数、系统负载、本机调度程序策略等情况,线程调度程序可能需要一些时间将新线程调度到物理内核以执行

  • 值得一提的是,
    yield()
    似乎与此无关……因为输出显示主线程中最后一个
    println
    发生在子线程中第一个之前。第一个
    yield()
    调用发生得太晚,对输出没有任何影响



    最后,正如javadoc所说:“使用这种方法很少合适。”.因此,试图通过实验找出它是如何工作的可能是浪费您的时间。

    我认为您的期望取决于误解。调度程序可以自行决定是否按任何顺序执行和交错。文档中没有任何内容表明您无法获得您观察到的输出。谢谢,伙计,但我得到了我想要的确切结果,实际上你的第一点救了我的命,我现在得到了我所期望的,请看我问题中的变化,请纠正我,如果我再次犯了错误谢谢你,我的问题现在已经解决了
    Main Thread
    Main Thread
    Main Thread
    Child Thread
    Main Thread
    Main Thread
    Main Thread
    Main Thread
    Main Thread
    Main Thread
    Main Thread
    Main Thread
    Child Thread
    Child Thread
    Child Thread
    Child Thread
    Child Thread
    Child Thread
    Child Thread
    Child Thread
    Child Thread
    Child Thread