2009-12-28 56 views
1

在下面的代碼中,我試圖通過產生較低優先級的線程來獲得更高優先級的線程來運行。但它似乎不工作,更高優先級的線程似乎在低優先級線程完成後運行。任何人都可以解釋我做錯了什麼?在Java 6中,爲什麼即使優先級較低的線程產量不高,優先級較高的線程也不會運行?

import java.util.ArrayList; 
import java.util.List; 

public class TestThreadPriority extends Thread { 

    static List<String> messages = new ArrayList<String>(); 

    public void run() { 
     Thread t = Thread.currentThread(); 
     int priority = t.getPriority(); 
     String name = t.getName(); 
     messages.add(name + ":" + priority);   
     Thread.yield(); 
     messages.add(name + ":" + priority); 
    } 

    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     Thread t = Thread.currentThread(); 
     t.setPriority(MIN_PRIORITY); 
     int priority = t.getPriority(); 
     String name = t.getName(); 
     messages.add(name + ":" + priority); 

     Thread tp1 = new TestThreadPriority(); 
     tp1.setPriority(MIN_PRIORITY);  
     Thread tp2 = new TestThreadPriority(); 
     tp2.setPriority(MAX_PRIORITY);  

     tp1.start(); 
     tp2.start(); 

     Thread.yield(); 
     messages.add(name + ":" + priority); 

     for(int i = 0; i < messages.size(); i++) { 
      System.out.println((i+1) + ". " + messages.get(i)); 
     } 
    } 
} 

輸出是:

  1. 主:1
  2. 線程0:1
  3. 線程0:1
  4. 主:1
  5. 線程1: 10
  6. Thread-1:10

任何幫助,非常感謝。

感謝, 奎德

+0

如果你在Linux上,另請參閱這個問題:http://stackoverflow.com/questions/1662185/do-linux-jvms-actually-implement-thread-priorities – JaakkoK 2009-12-28 21:28:04

回答

9

我猜你的第一個線程已經完成了第二個線程開始之前就執行。也許如果你的線程做了一些真正的工作(甚至只是睡了一下),你會看到來自兩個線程的重疊消息。

您的代碼的另一個問題是您正在訪問messages多個線程沒有同步。

你也應該與您試圖打印的messages內容,以確保您啓動線程已經登錄他們的信息和他們不嘗試修改,而你的列表之前已經開始的兩個線程加入我們正在迭代它來打印它。

修復了所有這些後,最後一點是這兩個線程正在產生,而不僅僅是較低優先級的線程。當更高優先級的線程產生時,低優先級線程獲得一些運行時間是完全合理的。擁有更高的優先權並不會給你一個壟斷。在你簡化的代碼示例中,優先級可能不會發生什麼變化 - 對於哪個線程首先觸及yield語句,大多數情況下都是偶然的。

+0

+1 - 打我。隨着一些更長的運行代碼,他可能會看到不同。 – 2009-12-28 20:42:31

+0

同步是你正在尋找或thread.sleep – Woot4Moo 2009-12-28 20:55:58

+0

謝謝馬克,這解釋了很多。我讀過當前正在運行的線程始終是線程池中相同或最高優先級的線程。這種說法是錯誤的嗎? – Quadir 2009-12-28 21:47:18

2

我讀到當前正在運行的線程始終是線程池中的最高優先級線程。這種說法是錯誤的嗎?

是的,這是錯誤的。事實上,Java語言規範或Java虛擬機規範都沒有提到線程優先級。和java.lang.Thread的javadoc說(只):

每個線程都有一個優先級。優先級較高的線程優先於較低優先級的線程執行。

事實上,Java的線程優先級模型是未指定的,線程優先級的影響是JVM,硬件和應用程序特定的。一些原因你的聲明(見上文)可能不正確如下:

  • 如果JVM使用多個處理器,可以合理預期的高和低優先級的線程同時運行。

  • 如果只有高優先級線程調用yield(),則較低優先級的線程將開始運行。

  • 如果在I/O調用中高優先級的線程阻塞,它可能不會在I/O完成時立即恢復。

  • 一些JVM的執行時間切片,它是可能一個低優先級的線程可能會被安排在只有高優先級線程的時間的幻燈片結束運行。 (在現實中,我不知道如果這種情況發生......但它無疑是要做到這一點,以減輕「優先級反轉」問題的一個很好的事情。)

在實踐中,這一切都意味着你應該不依賴於優先級給你細粒度的調度;例如通過調整優先級上下。你當然不應該使用優先級來代替正確的同步。