写多线程程序时,偶尔会遇到这么个场景:你手头有个循环任务,跑得飞快,占着CPU不放,结果把别的线程饿得直叫唤——比如UI卡顿、日志没及时刷、网络响应变慢。这时候,Thread.yield() 就像轻轻推了自己一把:‘我先歇半秒,你来’。
yield不是睡觉,是礼貌让座
很多人一看到“让出执行权”,就下意识以为它像 sleep(1) 那样停一会儿。其实不是。yield() 不设时间,也不进阻塞态,它只是向调度器说一句:‘我现在愿意让别人先跑’。至于调度器听不听?不一定。如果当前线程优先级高,或者没有其他同优先级的可运行线程,它可能马上又被挑中继续执行——就像地铁上你刚起身让座,结果发现没人要坐,只好又坐回去。
典型用法:忙等场景下的温柔刹车
比如一个自旋等待标志位的线程:
while (!ready) {
Thread.yield(); // 比空循环好,比sleep(1)轻量
}不用 yield(),它会死磕CPU;用 sleep(1),又可能延迟响应;而 yield() 刚好折中:不耗资源,也给其他线程露个缝儿。
注意边界:它不保证任何事
yield() 不同步、不释放锁、不改变线程状态(仍是 RUNNABLE),也不能替代 wait() 或 join()。它只在特定节奏感强的协作场景里有点用——比如多个工作线程轮着处理一批任务,谁干完一小块,就主动 yield 一下,让同伴跟上节奏,避免某线程一口气干到底,其他人干瞪眼。
再举个小例子:两个打印线程交替输出数字,不用锁也能靠 yield 碰运气协调(不严谨但能演示):
Thread t1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("A" + i);
Thread.yield();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("B" + i);
Thread.yield();
}
});
t1.start(); t2.start();输出可能是 A0 B0 A1 B1… 也可能全挤在一起——这恰恰说明 yield 的“建议性”:它只提意见,不发号施令。
所以别指望靠它做精确调度。真要控制顺序,还是老实用 synchronized、CountDownLatch 或 BlockingQueue。yield 只是工具箱里那把小镊子,夹不住大活儿,但有时候,顺手一夹,刚刚好。