Java 中 Thread.yield() 方法详解

对于很多初学 Java 线程的小伙伴们,很容易将 Thread 类里的 yield() 方法理解错误,或者理解得不够透彻,先看下源码:

public static native void yield();

是的,你没看错,Thread 类源码中定义的这个方法没有方法体,native 关键字修饰的方法表示原生态方法,方法对应的实现不在这个类文件里,而是在用其他语言(如 C 和 C++)实现的文件中。Java 语言本身不能对操作系统底层进行访问和操作(但可以通过 JNI 接口调用其他语言来实现对底层的访问)。所以,想要知道并理解 yield() 方法的具体实现过程,于初学者来说并没有必要。虽然“无代码无真相”,但采用大白话的解释或许更加通俗易懂吧。

Java线程调度的一点背景

在各种各样的线程中,Java 虚拟机必须实现一个有优先权的、基于优先级的调度程序。这意味着 Java 程序中的每一个线程被分配到一定的优先权,使用定义好的范围内的一个正整数表示。优先级可以被开发者改变。即使线程已经运行了一定时间,Java 虚拟机也不会改变其优先级。

优先级的值很重要,因为 Java 虚拟机和下层的操作系统之间的约定是操作系统必须选择有最高优先权的 Java 线程运行。所以我们说 Java 实现了一个基于优先权的调度程序。该调度程序使用一种有优先权的方式实现,这意味着当一个有更高优先权的线程到来时,无论低优先级的线程是否在运行,都会中断(抢占)它。这个约定对于操作系统来说并不总是这样,这意味着操作系统有时可能会选择运行一个更低优先级的线程。

理解线程的优先权

接下来,理解线程优先级是多线程学习很重要的一步,尤其是了解 yield() 函数的工作过程:

1、记住当线程的优先级没有指定时,所有线程都携带普通优先级。
2、优先级可以用从 1 到 10 的范围指定。10 表示最高优先级,1 表示最低优先级,5 是普通优先级。
3、记住优先级最高的线程在执行时被给予优先。但是不能保证线程在启动时就进入运行状态。
4、与在线程池中等待运行机会的线程相比,当前正在运行的线程可能总是拥有更高的优先级。
5、由调度程序决定哪一个线程被执行。
6、t.setPriority() 用来设定线程的优先级。
7、记住在线程 start() 方法被调用之前,线程的优先级应该被设定。
8、你可以使用常量,如 MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY 来设定优先级。

现在,我们对线程调度和线程优先级有一定理解了,进入主题。

Thread.yield() 方法会使当前线程从执行状态(运行状态)变为可执行状态(就绪状态)。CPU 会从众多的可执行态里选择,也就是说,当前也就是刚刚调用 yield() 方法的那个线程还是有可能会被再次继续执行的。yield() 方法并不是让当前线程暂停,让出时间片去执行其他线程,而在下一次时间片内就一定不会执行了(当前线程只是转换为就绪状态,在下一个本该是自己的却让给其他线程的时间片内也可能再次继续被执行)

很多人将 yield 翻译成线程让步。顾名思义,就是说当一个线程使用了这个方法之后,它就会把自己CPU执行的一段时间片让给自己或者其它的线程运行。

看如下例子:

public class TestYield {
	public static void main(String[] args) {
		MyThread3 t1 = new MyThread3("t1");
		MyThread3 t2 = new MyThread3("t2");
		t1.start();
		t2.start();
	}
}

class MyThread3 extends Thread {
	MyThread3(String s) {
		super(s);
	}
	
	public void run() {
		for (int i = 1; i <= 100; i++) {
			System.out.println(getName() + ": " + i);
			if (i % 10 == 0) {
				yield();
			}
		}
	}
}

再看运行结果:

.
.
.
t1: 8
t1: 9
t1: 10
t2: 6
t1: 11
.
.
.
t1: 18
t1: 19
t1: 20
t1: 21
t1: 22
.
.
.

t1: 10 后 t2: 6;t1: 20 后 t1: 21。

总结后可得以下重要的几点:

1、yield 是一个静态的原生(native)方法。
2、yield 告诉当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程。
3、yield 不能保证使得当前正在运行的线程迅速转换到可运行的状态。
4、它仅能使一个线程从运行状态转到可运行状态,而不是等待或阻塞状态。

转载于:https://my.oschina.net/u/3637389/blog/1863057

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值