yield()方法

操作系统为每个线程都分配了一个时间段来占用 CPU。通常情况下,只有在一个线程把分配给自己占用 CPU 的时间段使用完后,线程调度器才会进行下一轮的线程调度。这里提到的 “分配给(一个线程)占用CPU的时间段” 就是 CPU 分配给线程的执行权。

当一个线程通过某种方式向操作系统提出 “让出CPU执行权” 的请求时,就是在告知线程调度器当前线程将主动放弃由它占用 CPU 的时间段内还没有使用的部分,并在合适的情况下,重新获取新的、占用 CPU 的时间段。为了实现告知线程调度器当前线程请求让出 CPU 执行权的功能,Java 的 Thread 类提供了一个静态的 yield() 方法。yield() 方法的语法格式如下:

public static native void yield();

因为 yield() 方法是一个静态方法,所以可以由 Thread 类直接对其进行调用。在 yield() 方法的语法格式中,yield() 方法除被 static 修饰外,还被 native 修饰。那么,native 的作用是什么呢?抽象地讲,一个 Native Method 就是一个 Java 调用的非 Java 代码的接口。一个 Native Method 是一个由非 java 语言实现的方法。简单地讲,native 方法就是用于调用操作系统的方法接口,如Windows 系统的计算机会提供一个 yield() 方法,Linux 系统的计算机也会提供一个 yield() 方法。

yield 即“谦让”,使用 yield() 方法的目的是让具有相同优先级的线程之间能适当地被轮转执行。但是,实际中无法保证 yield() 方法达到谦让目的,因为放弃 CPU 执行权的线程还有可能被线程调度程序再次选中。暂停当前正在执行的线程对象(及放弃当前拥有的 CPU 执行权),并执行其他线程。yield() 方法做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。

【例21.1】从1加到10000000的执行时间(实例位置:资源包\TM\sl\21\1)

创建一个线程,线程名为 threadOne。输出一个数,该数的值为从1加到10000000的和;在不使用 yield() 方法的情况下执行程序,记录执行时间。代码如下:

public class Demo extends Thread {
    public void run() {
        long start = System.currentTimeMillis();
        int count = 0;
        for(int i = 0; i <= 10000000; i++) {
            count = count + i;
        }
        long end = System.currentTimeMillis();
        System.out.println("总执行时间:" + (end - start) + "毫秒");
    }

    public static void main(String[] args) {
        Demo threadOne = new Demo();
        threadOne.start();
    }
}

运行结果如下:

     总执行时间:7毫秒

加入 yield() 方法,再次执行程序,记录执行时间。

public class Demo1 extends Thread {
    @Override
    public void run() {
        long start = System.currentTimeMillis();
        int count = 0;
        for(int i = 0; i <= 10000000; i++) {
            count = count + i;
            this.yield();         // 加入 yield() 方法
        }
        long end = System.currentTimeMillis();
        System.out.println("总执行时间:" + (end - start) + "毫秒");
    }

    public static void main(String[] args) {
        Demo threadOne = new Demo();
        threadOne.start();
    }
}

运行结果如下:

     总执行时间:2565毫秒

从执行的结果来看,当加入 yield() 方法执行时,线程会让出 CPU 的执行权,并等待再次获取新的执行权,因此执行时间上会更加的长。

在实际的开发场景中,虽然 yield() 方法的使用场景比较少,但是在学习并发原理的过程中,理解 yield() 方法非常重要,有助于理解不同场景下的线程的不同状态。