Java執行緒Thread之yeild方法解析
轉載請標明出處:
http://blog.csdn.net/hesong1120/article/details/79032252
本文出自:hesong的專欄
Java執行緒Thread的yeild方法可能在日常使用中比較少出現,那它是做什麼用的,我們先查查官方文件解釋。
yield
public static void yield()
Causes the currently executing thread object to temporarily pause and allow other threads to execute.
看原版官方文件可以避免出現歧義,我的理解是
造成當前正在執行的執行緒物件臨時性的暫停,和允許其他執行緒去執行
也就是說,呼叫了yield方法之後,當前執行緒會臨時性的暫停一下,然後其他執行緒有機會去執行任務。那麼實際情況是怎麼樣,我們用例子來測試一下。
public class YieldTest{
private static final int DEST_NUM = 50;
public static void main(String[] args) {
new YieldTest();
}
public YieldTest(){
ThreadDemo yt1 = new ThreadDemo("張三" );
ThreadDemo yt2 = new ThreadDemo("李四");
ThreadDemo yt3 = new ThreadDemo("王五");
//yt1.setPriority(10);
//yt1.setPriority(5);
//yt3.setPriority(1);
yt1.start();
yt2.start();
yt3.start();
}
public class ThreadDemo extends Thread{
public ThreadDemo(String name){
setName(name);
}
@Override public void run() {
for (int i = 1; i <= DEST_NUM; i++) {
// 當i為30時,該執行緒就會把CPU時間讓掉,讓其他或者自己的執行緒執行(也就是誰先搶到誰執行)
if (i % 5 == 0) {
System.out.println("" + this.getName() + "-----" + i + " yeild一下");
yield();
}else{
System.out.println("" + this.getName() + "-----" + i);
}
}
}
}
}
上面的例子是,開啟張三,李四,王五三個執行緒分別列印從1到50的數字,每當列印的數字是5的倍數時(比如列印5,10,15等),就yield一下。那麼我們看看執行之後的結果是怎麼樣的。
張三-----1
王五-----1
李四-----1
王五-----2
王五-----3
王五-----4
張三-----2
張三-----3
王五-----5 yeild一下
李四-----2
李四-----3
李四-----4
李四-----5 yeild一下 /////////
李四-----6
李四-----7
李四-----8
王五-----6
王五-----7
王五-----8
王五-----9
王五-----10 yeild一下
張三-----4
張三-----5 yeild一下 //////////
張三-----6
張三-----7
張三-----8
張三-----9
張三-----10 yeild一下 /////////
張三-----11
張三-----12
張三-----13
張三-----14
張三-----15 yeild一下 /////////
張三-----16
張三-----17
張三-----18
張三-----19
//其餘的省略
。。。
可以看到這次張三雖然多次yeild了,但是依然繼續執行了。我們再執行一次看看
張三-----1
張三-----2
張三-----3
張三-----4
張三-----5 yeild一下
李四-----1
李四-----2
李四-----3
李四-----4
李四-----5 yeild一下
王五-----1
王五-----2
王五-----3
王五-----4
王五-----5 yeild一下
張三-----6
張三-----7
張三-----8
張三-----9
張三-----10 yeild一下
李四-----6
李四-----7
李四-----8
李四-----9
李四-----10 yeild一下
王五-----6
王五-----7
王五-----8
王五-----9
王五-----10 yeild一下
張三-----11
張三-----12
張三-----13
張三-----14
張三-----15 yeild一下
李四-----11
李四-----12
李四-----13
李四-----14
李四-----15 yeild一下
王五-----11
王五-----12
王五-----13
王五-----14
王五-----15 yeild一下
張三-----16
張三-----17
張三-----18
張三-----19
張三-----20 yeild一下
李四-----16
李四-----17
//其餘的省略
。。。
yield原理
發現這一次,每次呼叫了yeild之後,它們都沒有緊接著執行了。這是為什麼呢,難道yield沒有用處了嗎?
其實上面出現的不確定結果,是因為多核CPU執行的關係,一個執行緒呼叫了yield方法之後,確實會讓出當前使用的CPU,讓自己從【執行態】變為【就緒態】。
- 當執行環境是單核CPU的時候。如果其他執行緒已經處於就緒態,正在等待CPU時間片時,這時有執行緒yield讓出了CPU時間片,它們中的一個就會先有可能分配到CPU時間片,進而進入【執行態】,執行執行緒內容。
- 而當執行環境是多核CPU的話。也許上面的三個執行緒都是同時處於【執行態】正在執行,那個一個執行緒yiedl之後,短暫的讓出了它的CPU,而此時又沒有執行緒跟它搶CPU(因為其他兩個都在執行著),所以它可能又獲得了CPU時間片又去執行了。所以針對多核CPU環境的話,測試結果並沒有明顯的規律。
yield錯誤觀點糾正
網上有說“yield之後,只有同優先順序的執行緒能執行,低優先順序的執行緒無法獲得執行”,這是錯誤的觀點,Java文件並沒有這種說,Java虛擬機器也並沒有這種限制。會大概率出現這種情況主要是因為yield之後,高優先順序的執行緒會更容易得到排程優先得到CPU時間片執行,低優先順序自然被執行的概率就更少了,但是並不是說低優先順序執行緒就無法被執行。可以把上面程式碼的優先順序設定部分註釋去掉,自己親自執行看看結果,別被誤導了。
yield的使用場景
yield的作用就是暫時讓出使用著的CPU,這樣其他【就緒態】的執行緒就有機會佔用這個CPU去執行。所以yield的使用場景多在,當前執行緒在進行耗時性的操作時(如IO操作),並且因為它的優先順序較高,導致一些優先順序較低的執行緒被分配的時間片更少,這樣優先順序低的執行緒就要等待更長時間才能完成操作,那麼這時適當地呼叫幾次yield方法讓出CPU,讓優先順序低的執行緒多得到執行,這樣才能高效的實現程式執行和響應。
我的部落格
GitHub
我的簡書
群號:194118438,歡迎入群
微信公眾號 hesong ,微信掃一掃下方二維碼即可關注: