/**(1)
* A hint to the scheduler that the current thread is willing to yield
* its current use of a processor. The scheduler is free to ignore this
* hint.
*(2)
* <p> Yield is a heuristic attempt to improve relative progression
* between threads that would otherwise over-utilise a CPU. Its use
* should be combined with detailed profiling and benchmarking to
* ensure that it actually has the desired effect.
*(3)
* <p> It is rarely appropriate to use this method. It may be useful
* for debugging or testing purposes, where it may help to reproduce
* bugs due to race conditions. It may also be useful when designing
* concurrency control constructs such as the ones in the
* {@link java.util.concurrent.locks} package.
*/
public static native void yield();
(1)當前線程暗示調度器,它願意讓出對CPU的使用。調度器可以忽略這個暗示,也可以做出相應處理。
說明:如果調度器忽略了這個暗示,那麼當前線程將會繼續執行,不會停止。如果調度器沒有忽略,則當前線程會從執行狀態轉化爲就緒狀態,然後調度器會從就緒狀態的線程中,選擇一個出來,讓它使用CPU。
(2)yield方法的初衷是爲了提高線程之間的相對進度,防止過度使用CPU的。所以yield方法的使用,一定要經過詳細的分析和測試,確保yield能達到預期的效果。
說明:也就是說要知道yield方法可能會被忽略。我們要在這個前提下,去正確使用yield。
(3)適合yield方式使用的場景不多。有需要使用到的地方,一個是競態條件下爲了復現bug,使用yield用於調試。另一個是同步控制的設計需要。
下面舉個例子,說明一個yield的使用場景(一定是和while()循環搭配使用的):
public static void main(String[] args) throws InterruptedException {
final AtomicInteger ai = new AtomicInteger(1);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (!ai.compareAndSet(2, 3))
Thread.yield();//當ai的值還沒有被賦值爲2的時候,線程讓出CPU使用權
}
});
t.start();
if (ai.compareAndSet(1, 2)) {//將2賦值給ai
t.join();//等待t線程運行完再往下執行,相當於把線程t的代碼加進來了
if (!t.isAlive()) {
int a = ai.get();
System.out.println("a = " + a);//a = 3
} else {
System.out.println("t線程還在運行中");//如果t.join()註釋掉的話,會打印這句,否則永遠不會打印
}
}
}
可以看出來,t 線程想要把ai的值從2更新爲3,需要等待主線的把ai的值從1更新爲2以後。所以線程 t 在更新ai值失敗以後,調用yield方法,讓出了cpu的使用權。如果這時候被調度器忽略的,會繼續去更新ai的值。這是ai的值可能是2了,也可能不是。如果不是,t線程會繼續重複上述步驟,直到成功賦值爲3。(和我們預期的是一樣的)
覺得有用的老鐵們贊一下唄,謝謝!