Java 並發 線程的優先級
@author ixenos
低優先級線程的執行時刻
1.在任意時刻,當有多個線程處於可運行狀態時,運行系統總是挑選一個優先級最高的線程執行,只有當線程停止、退出或者由於某些原因不執行的時候,低優先級的線程才可能被執行
2.兩個優先級相同的線程同時等待執行時,那么運行系統會以round-robin的方式選擇一個線程執行(即輪詢調度,以該算法所定的)(Java的優先級策略是搶占式調度!)
3.被選中的線程可因為一下原因退出,而給其他線程執行的機會:
1) 一個更高優先級的線程處於可運行狀態(Runnable)
2)線程主動退出(yield),或它的run方法結束
3)在支持分時方式的系統上,分配給該線程的時間片結束
4.Java運行系統的線程調度算法是搶占式(preemptive)的,當更高優先級的線程出現並處於Runnable狀態時,運行系統將選擇高優先級的線程執行
5.例外地,當高優先級的線程處於阻塞狀態且CPU處於空閑時,低優先級的線程也會被調度執行
1 public class PriorityExample{ 2 public static void main(Strinig[] args){ 3 Thread a = new PThread("A"); 4 Thread b = new PThread("B"); 5 a.setPriority(7); //設置優先級 6 a.setPriority(1); 7 } 8 } 9 10 class PThread extends Thread{ 11 public PThread(String n){ 12 super(n); 13 } 14 15 public void run(){ 16 for(int i=0; i<5000000; i++){ 17 if(i%5000000 == 0){ 18 System.out.print(getName()); 19 } 20 } 21 } 22 }
輸出 AAAAAAAAABBBBBBBBB
利己線程
1.一般地,在線程中可以調用sleep方法,放棄當前線程對處理器的使用,從而使各個線程均有機會得到執行,但有時候線程可能不遵循這個規則!
1 public void run(){ 2 for(int i=0; i<5000000; i++){ 3 if(i%5000000 == 0){ 4 System.out.print(getName()); 5 } 6 } 7 }
2.for循環是一個緊密循環,一旦運行系統選擇了有for循環體的線程執行,該線程就不會放棄對處理器的使用權,除非for循環自然終止或者該線程被一個有更高優先級的線程搶占,這樣的線程稱為利己線程
3.利己線程一般不引起問題,但有時會讓其他的線程得到處理器使用權之前等待一段很長的時間
分時方式
1.為解決利己線程可能長時間占據CPU的問題,有些系統通過分時方式來限制利己線程的執行,如Windows2000或WindowsNT系統
2.在分時方式中,處理器的分配按照時間片來划分,對於那些具有相同最高優先級的多個線程,分時技術會交替地分配CPU時間片給他們執行,當時間片結束,即使該線程沒有運行結束,也會讓出CPU使用權
3.注釋掉優先級設置后,輸出變成了AAAAABBBBBAAABBB或者AABBAAAABBBBAABBA
1 public class PriorityExample{ 2 public static void main(Strinig[] args){ 3 Thread a = new PThread("A"); 4 Thread b = new PThread("B"); 5 //a.setPriority(7); //設置優先級 6 //a.setPriority(1); 7 } 8 } 9 10 class PThread extends Thread{ 11 public PThread(String n){ 12 super(n); 13 } 14 15 public void run(){ 16 for(int i=0; i<5000000; i++){ 17 if(i%5000000 == 0){ 18 System.out.print(getName()); 19 } 20 } 21 } 22 }
而如果在另一個不支持分時技術的平台上運行程序,得到的輸出結果可能是確定的! AAAAAAAAABBBBBBBBB
4.Java運行系統不實現分時,分時是和平台相關的,而有的平台不支持分時,在編寫Java多線程程序的時候,不能過分依賴分時技術來保證各個線程都有公平的執行機會!通常應編寫那種可以主動放棄處理器使用權的程序,同時一個線程也可以調用yield方法主動放棄對處理器的使用權
注意:使用yield只能給同優先級的線程提供執行機會,如果沒有同優先級的線程處於可運行狀態,yield方法將被忽略!