【问题标题】:some doubts regarding yield()关于 yield() 的一些疑问
【发布时间】:2012-04-02 02:03:16
【问题描述】:

关于 Thread.yield() 方法的一些问题。我的理解是当我们调用Thread.Yield()时,当前运行的线程会回到可运行状态。所以依赖线程优先级的线程调度器会执行下一个更高优先级的线程。现在我有一个示例程序。请看下文。

package thread;

public class YieldTest implements Runnable {

    @Override
    public synchronized  void run() {
        System.out.println(Thread.currentThread().getName()+", executing..");
        for(int i = 0 ; i <5;i++){
            if(i==2){               
                Thread.yield();
                System.out.println(Thread.currentThread().getName()+": "+i+" yielded()");
                /*try {
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName()+": "+i+" yielded()");
                } catch (InterruptedException e) {

                    e.printStackTrace();
                }*/

            }else{
                System.out.println(Thread.currentThread().getName()+": "+i);
            }

        }       
    }


public static void main(String[] args) {

    YieldTest test = new YieldTest();
        Thread t1 = new Thread(test);
        t1.setName("A");
        t1.setPriority(9);
        Thread t2 = new Thread(test);
        t2.setName("B");
        Thread t3 = new Thread(test);
        t3.setName("C");

        t2.setPriority(6);
        t2.setPriority(4);

        t1.start();
        t2.start();
        t3.start();

    }


}

在这里,我总是通过以下方式获取输出,

A, executing..
A: 0
A: 1
A: 2 yielded()
A: 3
A: 4
C, executing..
C: 0
C: 1
C: 2 yielded()
C: 3
C: 4
B, executing..
B: 0
B: 1
B: 2 yielded()
B: 3
B: 4

现在的问题是 yield() 方法应该回到可运行状态,其他线程应该执行。所以输出应该类似于以下方式

A,正在执行.. 答:0 答:1 A: 2 产生()

C,正在执行.. C: 0 C: 1 C: 2 产生()

A: 3
A: 4

B,执行.. 乙:0 乙:1 B: 2 产生()

C: 3
C: 4

B: 3
B: 4

另外,线程优先级如何。不保证为什么我们需要线程优先级?如果我错了请纠正我。

【问题讨论】:

  • 您真正想解决什么问题?调用yield() 可能不是最好的解决方案。
  • 有关yield()的更多信息,请参阅this question
  • 在这种特殊情况下,如果线程 A 在 B 有时间启动之前完成,我不会感到惊讶。

标签: java


【解决方案1】:

你是对的,线程优先级不能保证。这只是对 JVM 的一个建议,JVM 在决定实际运行哪个线程时可以考虑其他因素。从技术上讲,JVM 甚至可以根据需要随意选择,并且仍然符合the JVM specification

【讨论】:

    【解决方案2】:

    您的所有运行方法都在同一个对象(测试)上同步。所以 yield 没有任何作用,因为在第一个线程的 run 方法退出之前,没有其他人可以进入他们的 run() 方法。

    基本上线程 1 启动,并进入 run() 方法。这在“this”上同步。输出2个数字后,它产生了。但是线程 2 和 3 都在等待进入 run 方法,因为它们无法在测试时获得监视器。所以 yield 没有做任何事情。一旦线程一完成,同样的问题就会发生。

    【讨论】:

    • 好的,谢谢好信息。如果不同步,那我们就不能像oe thread那样在一个线程之后实现属性结果..
    【解决方案3】:

    所以当 Java 使用绿色线程时,yield 更有用。现在,虽然它会通知操作系统,但可以将线程置于等待状态(不可运行)。但是,线程是否会真正让步以允许另一个线程运行,这实际上取决于操作系统和 JVM。哪个线程是你无法控制的。

    但是,最终我从未将 yield 用于任何事情。你到底想用它做什么?

    【讨论】:

    • 所以我们不应该使用或避免使用 Thread.yield(),因为它完全依赖于平台和 JVM。那是对的吗?代替 Yield() 更好地使用 wait()。我说的对吗?
    • 问题不在于可移植性,而在于控制。您没有足够的控制权使用 yield 在线程之间进行任何形式的同步。我想不出 yield 可以解决的问题。您的问题的问题在于您询问了产量,但并没有真正说明为什么您认为需要产量。使用 wait/notify/notifyAll 和 synchronize 以获得完全控制,但同样还有其他通常更容易的方法。它只是归结为你想做什么?
    【解决方案4】:

    Thread.yield:这是一个静态方法,本质上是用来通知系统当前线程愿意“放弃CPU”一段时间。

    线程调度器可以选择一个不同的线程来运行而不是当前线程。

    但是,线程调度程序如何实现屈服的细节因平台而异。一般来说,您不应该依赖它以特定方式表现。不同之处包括:

    1.when, after yielding, the thread will get an opportunity to run again;
    2.whether or not the thread forgoes its remaining quantum. 
    

    线程优先级:

    在任何给定时间,最高优先级的线程都在运行。但是,这不能保证。线程调度程序可以选择运行较低优先级的线程以避免饥饿。因此,出于效率目的,仅使用优先级来影响调度策略。

    【讨论】:

      【解决方案5】:

      Thread.yield() 之类的线程优先级只是对操作系统的建议。不能保证 yield() 会停止当前线程。它不能保证更高优先级的线程将在此时运行,因为操作系统可以在任何地方停止您的线程。不能保证更高优先级的线程会有更高的优先级,否则会产生任何影响。

      恕我直言,尝试用 Java 编写自己的调度程序不是一个好主意。它不太可能以您认为的方式提供帮助或行为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-07
        • 2012-12-01
        • 2018-08-04
        • 2020-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多