Java Thread.yield()简介

2023/06/07

1. 概述

在本教程中,我们将探讨Thread类中的yield()方法。

我们将把它与Java中可用的其他并发习语进行比较,并最终探索它的实际应用。

2. yield()介绍

正如官方文档所建议的那样,yield()提供了一种机制来通知“调度器”当前线程愿意放弃其当前使用的处理器,但它希望尽快被调度回来

“调度器”可以自由地遵守或忽略此信息,事实上,根据操作系统的不同,它具有不同的行为。

以下代码片段显示两个线程在每个调度后以相同的优先级屈服:

public class ThreadYield {
    public static void main(String[] args) {
        Runnable r = () -> {
            int counter = 0;
            while (counter < 2) {
                System.out.println(Thread.currentThread().getName());
                counter++;
                Thread.yield();
            }
        };
        new Thread(r).start();
        new Thread(r).start();
    }
}

当我们尝试多次运行上述程序时,我们会得到不同的结果;其中一些如下所述:

Thread-0
Thread-0
Thread-1
Thread-1
Thread-0
Thread-1
Thread-1
Thread-0

因此,正如你所看到的,yield()的行为是不确定的并且也依赖于平台。

3. 与其他的方法使用相比

还有其他结构可以影响线程的相对进度。它们包括Object类中的wait()、notify()和notifyAll()、以及Thread类中的join()和sleep()。

让我们看看它们与yield()相比如何。

3.1 yield()与wait()

  • yield()是在当前线程的上下文中调用的,而wait()只能在同步块或方法中显式获取的锁上调用
  • 与yield()不同,wait()可以指定在任何尝试再次调度线程之前等待的最短时间段
  • 使用wait()还可以通过调用相关锁对象上的notify()或notifyAll()随时唤醒线程

3.2 yield()与sleep()

  • yield()只能试探性地尝试暂停当前线程的执行,但不能保证它何时会被调度回来,而sleep()可以强制调度程序将当前线程的执行暂停至少一段时间。

3.3 yield()与join()

  • 当前线程可以在任何其他线程上调用join(),这会使当前线程在继续之前等待其他线程结束
  • 可选地,它可以使用一个时间段作为参数,该时间段指示当前线程在恢复之前应该等待的最长时间

4. yield()的用法

正如官方文档所暗示的那样,很少有必要使用yield(),因此应该避免使用,除非根据其行为非常清楚目标。

尽管如此,yield()的一些用途包括设计并发控制结构,提高计算量大的程序中的系统响应能力等。

但是,这些用法必须伴随着详细的分析和基准测试,以确保获得预期的结果。

5. 总结

在这篇简短的文章中,我们讨论了Thread类中的yield()方法,并通过一段代码了解了它的行为和局限性。

我们还探讨了它与Java中可用的其他并发习语的比较,并最终研究了yield()可能有用的一些用例。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章