在篮球比赛中,我们经常会看到两队选手互相抢篮球,当某个选手抢到篮球后就可以拍一会,之后他会把篮球让出来,其他选手重新开始抢篮球,这个过程就相当于 Java 程序中的线程让步。所谓的线程让步是指正在执行的线程,在某些情况下将 CPU 资源让给其他线程执行。

    线程让步可以通过 yield()方法来实现,该方法和 sleep()方法有点相似,都可以让当前正在运行的线程暂停,区别在于 yield()方法不会阻塞该线程,它只是将线程转换成就绪状态,让系统的调度器重新调度一次。当某个线程调用 yield()方法之后,只有与当前线程优先级相同或者更高的线程才能得到执行的机会。

    接下来通过一个案例来演示一下 yield()方法的使用,如下所示。

    1. public class example08 {
    2. public static void main(String[] args) {
    3. //创建两个线程
    4. Thread t1 = new YieldThread("线程A");
    5. Thread t2 = new YieldThread("线程B");
    6. //开启两个线程
    7. t1.start();
    8. t2.start();
    9. }
    10. }
    11. //定义 YieldThread 类继承 Thread 类
    12. class YieldThread extends Thread{
    13. //定义一个有参的构造方法
    14. public YieldThread(String name) {
    15. super(name); //调用父类的构造方法
    16. }
    17. @Override
    18. public void run() {
    19. super.run();
    20. for (int i = 0; i < 10; i++) {
    21. System.out.println(Thread.currentThread().getName() + "---" + i);
    22. if (i == 5) {
    23. System.out.print("线程让步:");
    24. Thread.yield(); //线程运行到此,作出让步
    25. }
    26. }
    27. }
    28. }

    运行结果如下所示。
    QQ截图20200709151518.png
    书上的解释出现了错误,后翻阅资料得知:
    (2020/7/26 update 书上的解释没有错误,是我当时理解错了)
    ~~
    上述代码块中创建了两个线程 t1 和 t2,它们的优先级相同。两个线程在循环变量 i 等于 5 时,都会调用 Thread 的yield()方法,使当前的线程暂停,这时另一个线程就会获得执行。从运行结果可以看出,当线程 A 输出 5 后,会做出让步,线程 A 继续执行。同样,线程 B 输出 5 后,也会做出让步,线程 A 继续执行。

    yield()方法只是使当前线程从执行状态(运行状态)回到可执行状态(就绪状态),执行完 yield()的线程有可能在进入到可执行状态又立刻被执行。另外 yeild()方法只能使同优先级或者更高优先级的线程得到执行机会(这是个错误的结论,故打上删除线)

    对于线程的运行,它有一个时间片的概念,线程优先级低的在拿到时间片时也是可以执行的,只不过优先级高的线程会尽可能早的执行罢了,不是说优先级高的一定会先执行。

    抢占式调度模式时,高级别的线程优先执行,如果低级别的线程正在运行,有高级别线程可运行状态,则会执行完低级别线程,再去执行高级别线程。如果低级别线程处于等待、睡眠、阻塞状态,可以调用yield()函数让当前运行线程回到可运行状态,以允许具有相同优先级或者高级别的其他线程获得运行机会。

    因此,使用 yield()的目的是让相同优先级的线程之间能适当的轮转执行。

    但是,实际中无法保证 yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。

    所以,对于 yield()方法,可以理解为当前线程是让出了执行权,但是还是要看时间片分到了谁。就算当前线程现在让出了执行权,可能马上它又得到执行权接着执行。

    结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但可能没有效果。

    举个例子:
    一帮朋友在排队上公交车,轮到 Yield 的时候,他突然说:我不想先上去了,咱们大家来竞赛上公交车。

    然后所有人就一块冲向公交车,有可能是其他人先上车了,也有可能是 Yield 先上车了。

    虽然线程是有优先级的,但是优先级越高的人,就一定能第一个上车吗?这是不一定的,优先级高的人仅仅只是第一个上车的概率大了一点而已,最终第一个上车的,也有可能是优先级最低的人。

    所谓的优先级执行,是在大量执行次数中才能体现出来的。