(一)java yield()方法注釋:
/*** 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.** <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.** <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.*/
大致意思:yield()方法會通知線程調度器放棄對處理器的占用,但調度器可以忽視這個通知。yield()方法主要是為了保障線程間調度的連續性,防止某個線程一直長時間占用cpu資源。但是他的使用應該基于詳細的分析和測試。這個方法一般不推薦使用,它主要用于debug和測試程序,用來減少bug以及對于并發程序結構的設計。
(二)方法理解:
Thread.yield()翻譯成中文就是讓步的意思,根據語義理解就是線程讓出當前時間片給其他線程執行。這個函數在JSL中未給出明確的語義,就是沒有要求具體如何實現,這取決于各個不同jvm的具體實現。部分jvm在執行這個函數時可能什么都不做,但是大部分jvm的實現都是:將線程從running狀態轉為runnable狀態,然后放入同優先級等待隊列的末尾,等待前面所有相同優先級的線程調度完成后才可能再度獲得執行機會。不過當同優先級隊列中剛好只剩這個線程時,那么這個線程可能很快就又獲得了cpu時間片。我們常用的HotSpot默認采用的是第二種方式。
我們再看個小例子:
public class YieldTest extends Thread {public YieldTest(String name) {super(name);}@Overridepublic void run() {for (int i = 1; i <= 1000; i++) {System.out.println("" + this.getName() + "-----" + i);if (i == 30 || i == 100 || i == 500 || i == 700 || i == 800 || i == 900) {Thread.yield();}}}public static void main(String[] args) {YieldTest yt1 = new YieldTest("張三");YieldTest yt2 = new YieldTest("李四");yt1.start();yt2.start();}
}
運行結果:
我們會驚奇的發現:調用Thread.yield()后線程并不一定會立刻停止執行,i == 100時調用Thread.yield()后線程沒有立刻放棄cpu時間片,李四這個無恥之徒還在執行呢!
這個主要是因為張三從runnable狀態切換到running狀態是需要一些準備的,這個需要耗費一些時間。系統為了避免cpu資源的浪費還會讓李四在執行一小段時間。不過調度器后面一定會讓張三執行下的,面子工程必須得做的。所以就如同yield()方法注釋中說的,業務代碼使用這個函數需慎重。
?