概念
我們知道 start() 方法是啟動線程,讓線程變成就緒狀态等待 CPU 排程後執行。
那 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.
*/
public static native void yield();
yield 即 “謙讓”,也是 Thread 類的方法。它讓掉目前線程 CPU 的時間片,使正在運作中的線程重新變成就緒狀态,并重新競争 CPU 的排程權。它可能會擷取到,也有可能被其他線程擷取到。
實戰
下面是一個使用示例。
/**
* 微信公衆号:Java技術棧
*/
public static void main(String[] args) {
Runnable runnable = () -> {
for (int i = 0; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + "-----" + i);
if (i % 20 == 0) {
Thread.yield();
}
}
};
new Thread(runnable, "棧長").start();
new Thread(runnable, "小蜜").start();
}
這個示例每當執行完 20 個之後就讓出 CPU,每次謙讓後就會馬上擷取到排程權繼續執行。
運作以上程式,可以有以下兩種結果。
結果1:棧長讓出了 CPU 資源,小蜜成功上位。
棧長-----29
棧長-----30
小蜜-----26
棧長-----31
結果2:棧長讓出了 CPU 資源,棧長繼續運作。
棧長-----28
棧長-----29
棧長-----30
棧長-----31
而如果我們把兩個線程加上線程優先級,那輸出的結果又不一樣。
thread1.setPriority(Thread.MIN_PRIORITY);
thread2.setPriority(Thread.MAX_PRIORITY);
因為給小蜜加了最高優先權,棧長加了最低優先權,即使棧長先啟動,那小蜜還是有很大的機率比棧長先會輸出完的,大家可以試一下。
yield 和 sleep 的異同
1)yield, sleep 都能暫停目前線程,sleep 可以指定具體休眠的時間,而 yield 則依賴 CPU 的時間片劃分。
2)yield, sleep 兩個在暫停過程中,如已經持有鎖,則都不會釋放鎖資源。
3)yield 不能被中斷,而 sleep 則可以接受中斷。
總結
棧長沒用過 yield,感覺沒什麼鳥用。
如果一定要用它的話,一句話解釋就是:yield 方法可以很好的控制多線程,如執行某項複雜的任務時,如果擔心占用資源過多,可以在完成某個重要的工作後使用 yield 方法讓掉目前 CPU 的排程權,等下次擷取到再繼續執行,這樣不但能完成自己的重要工作,也能給其他線程一些運作的機會,避免一個線程長時間占有 CPU 資源。
動手轉發給更多的朋友吧!