线程的yield操作的作用是让出目前正在执行的线程放弃当前的执行,让出CUP权限,使得CPU去执行其他的线程。处于让步状态的JVM层面的线程状态仍然是RUNNABLE状态,但是该线程所对应的操作系统层面的线程从状态上来说会从执行状态编程就绪状态。线程yield时,线程放弃和重占CPU的时间是不确定的,可能是刚刚放弃CPU,马上又获得CPU执行权限,重新开始执行。
yield0方法是Thread类提供的一个静态方法,它可以让当前正在执行的线程暂停,但它不会阻寒该线程,只是让线程转入就绪状态。yield只是让当前线程暂停一下,让系统的线程调度器重新调度一次,yield()方法只有一个版本。
--javascripttypescriptbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
package day07; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; /** * yield: * 让出CUP时间片,让CUP去调用其他线程。 * 但是当前线程的状态依然是RUNNABLE * 虽然让出时间片,但是有可能,CPU进行调度的时候,依然会继续执行。 * */ public class Demo07 { public static final int count = 1000; public static AtomicInteger runCount = new AtomicInteger(0); public static Map<String,AtomicInteger> map = new HashMap<>(); public static void main(String[] args) throws InterruptedException { MyThread myThread01 = new MyThread(); MyThread myThread02 = new MyThread(); myThread01.start(); myThread02.start(); Thread.sleep(5000); System.out.println(map); } /** * 打印出线程的执行次数 */ static class MyThread extends Thread{ static int threadNum = 1; public MyThread() { super("Thread-"+threadNum); threadNum++; map.put(this.getName(), new AtomicInteger(0)); } @Override public void run() { for (int i = 0; i < count && runCount.get()<count; i++) { runCount.incrementAndGet(); map.get(this.getName()).incrementAndGet(); if (i % 2 == 0) { Thread.yield(); } } } } }
在以上演示案例中,一共启动了两个让步演示线程,两个线程每执行两次操作就让出CPU。但是两个线程的优先级有区别,Thread-1的优先级为10, Thread-2的优先级为1,从输出的结果可以看出,优先级高的 Thread-1执行的次数比优先级低的Thread-2在执行的次数多很多。得到的结论是:线程调用yield之后,操作系统在重新进行线程调度时偏向于将执行机会让给优先级较高的线程。
总结起来,Thread.yield()方法有以下特点:
1)yield仅能使一个线程从运行状态转到就绪状态,而不是阻塞状态。
2)yield不能保证使得当前正在运行的线程状态迅速转到就绪状态。
3)即使完成了迅速切换,系统通过线程调度机制从所有就绪线程中挑选下一个执行线程时,就绪的线程有可能被选中,也有可能不被选中,其调度的过程受其他因素(如优先级)的影响。