2012-05-29 87 views
4

我是新來的Java和threads..I的世界,通過一個示例代碼正要如下: -理解 「優先級」,在Java線程

package com.alice.learnthread; 

class NewThread implements Runnable{ 
Thread t; 
long clicker=0; 

private volatile boolean running=true; 
NewThread(int p){ 
    t=new Thread(this); 
    t.setPriority(p); 
} 
public void run(){ 
    while(running){ 
     clicker++; 
    } 
} 
public void stop(){ 
    running=false; 
} 
public void start(){ 
    t.start(); 
} 

}

public class TestThread { 
public static void main(String[] args){ 
    Thread r=Thread.currentThread(); 
    r.setPriority(Thread.MAX_PRIORITY); 
    NewThread hi=new NewThread(Thread.NORM_PRIORITY+2); 
    NewThread lo=new NewThread(Thread.NORM_PRIORITY-2); 
    hi.start(); 
    lo.start(); 
    try{ 
     r.sleep(5000); 
    }catch(InterruptedException e){ 
     System.out.println("caught"); 
    } 
    hi.stop(); 
    lo.stop(); 
    try{ 
     hi.t.join(); 
     lo.t.join(); 
    }catch(InterruptedException e){ 
     System.out.println("cau1"); 
    } 
    System.out.println("hi = "+hi.clicker+" lo="+lo.clicker); 
} 

}

但是根據本書的輸出結果,具有高優先級的線程應該具有較高的變量答題器值。但在我的情況下,該變量唱首歌值是比更高的優先級one.The輸出就像下面我低優先級的線程要高得多: -

hi = 2198713135 lo=2484053552 

這是否並不意味着低優先級的線程獲得更多的CPU時間比更高的優先級...我缺少的東西..結果是相同的(對較低的優先級線程更高的喀value聲值)在Ubuntu和WIN7 ...

+3

2個線程每一個可能有自己的CPU內核,從來就沒有將涉及優的爭奪。我猜如果你有10個線程,你可能會看到預期的行爲。但即使如此,Java線程調度程序比搶先式更合作,所以如果沒有明確的'yield()'調用,您可能仍會得到「有趣」的結果。 –

+0

除了上面的內容,對於你的問題的答案是「這不是說較低優先級的線程比較高優先級的線程獲得了更多的CPU時間......」是..不。 –

+0

@鶴山那是什麼意思? – Rasmus

回答

2

正如sul所言,優先級更多的是一個暗示,而不是JVM的契約。 在你的情況,你的結果可以通過幾種理論來解釋:

  • 第二個線程運行得更快,因爲它需要的第一個彙編的好處,第一個後停止。
  • while循環檢查volatile變量的值強制jvm實現該值,在此期間可能會給其他線程提供CPU。
  • 停止方法花費大量時間來停止線程。

這只是一些事實,可以說線程行爲是不可預測的。例如,嘗試先啓動低優先級的線程,我相信你會得到不同的結果。

而且,試試這個:

public class TestThread 
{ 
    public static void main(String[] args){ 
     Thread r=Thread.currentThread(); 
     r.setPriority(Thread.MAX_PRIORITY); 
     NewThread hi=new NewThread(Thread.MAX_PRIORITY); 
     NewThread lo=new NewThread(Thread.MIN_PRIORITY); 
     hi.start(); 
     lo.start(); 
     try{ 
      r.sleep(5000); 
     }catch(InterruptedException e){ 
      System.out.println("caught"); 
     } 
     hi.interrupt(); 
     lo.interrupt(); 

     System.out.println("hi="+hi.clicker); 
     System.out.println("lo="+lo.clicker); 
    } 
} 
class NewThread extends Thread{ 
    long clicker=0; 

    NewThread(int p){ 
     setPriority(p); 
    } 
    public void run(){ 
     while(true){ 
      clicker++; 
     } 
    } 
} 

我相信,除去揮發性變量和更改線程如何停止會給你一個其他的結果。

+0

感謝您的明確解釋 – Rasmus

+1

您應該有一個其他更改是使while循環isInterupted()而不是true。 –

0

線程在本質上不可預測的。低優先級線程在高優先級線程由於某些原因而無法運行時運行,此外,當所有線程都競爭CPU時,線程優先級並不十分有意義。

但是,當我執行上面的程序,我得到了你的書中提到的理想結果。

hi = 1707497920 lo=1699648942 

hi = 1702682202 lo=1685457297 
0

我發現在Windows 7上,如果我增加線程的數量,那裏是對系統資源的實際鬥爭,增加跑的時間點,高優先級的線程執行的順序更多的點擊量。如果情況並非如此,會好奇。我認爲你的測試用例在線程數量上太少,以至於無法使用足夠的資源來爭奪它們,並且還會在運行時讓JVM綁定到本地線程。

public static void main(String[] args) { 
     Thread r = Thread.currentThread(); 
     r.setPriority(Thread.MAX_PRIORITY); 
     List<NewThread> hiThreads = new LinkedList<NewThread>(); 
     List<NewThread> lowThreads = new LinkedList<NewThread>(); 
     for (int i = 0; i < 10; i++) { 
      NewThread hi = new NewThread(Thread.NORM_PRIORITY + 2); 
      NewThread lo = new NewThread(Thread.NORM_PRIORITY - 2); 
      hiThreads.add(hi); 
      lowThreads.add(lo); 
      hi.start(); 
      lo.start(); 
     } 
     try { 
      r.sleep(30000); 
     } catch (InterruptedException e) { 
      System.out.println("caught"); 
     } 
     for (NewThread h : hiThreads) { 
      h.stop(); 
     } 
     for (NewThread l : lowThreads) { 
      l.stop(); 
     } 
     try { 
      for (NewThread h : hiThreads) { 
       h.t.join(); 
      } 
      for (NewThread l : lowThreads) { 
       l.t.join(); 
      } 
     } catch (InterruptedException e) { 
      System.out.println("cau1"); 
     } 
     long hiClicker = 0l; 
     for (NewThread h : hiThreads) { 
      hiClicker += h.clicker; 
     } 
     long lowClicker = 0l; 
     for (NewThread l : lowThreads) { 
      lowClicker += l.clicker; 
     } 
     System.out.println("hi = " + hiClicker + " lo=" + lowClicker); 
    } 
0

只是爲那些誰尋求多一點的解釋... 以下是「完全參考,Java中的摘錄,Herbert Shieldt「

作爲絕對值,優先級是無意義的;如果它是唯一運行的線程,則優先級更高的線程的運行速度不會低於優先級更低的線程。 相反,線程的優先級用於決定何時從一個正在運行的線程切換到下一個線程。這被稱爲上下文切換。確定上下文切換何時發生的規則很簡單:

  • 線程可以自動放棄控制權。這通過顯式地 產生,休眠或阻塞待處理的I/O來完成。在這種情況下,將檢查所有其他 線程,並且已準備好運行的最高優先級線程在給定CPU的情況下爲 。
  • 線程可以被更高優先級的線程搶佔。在這種情況下,不會產生處理器的優先級較低的線程將被優先級較高的線程簡單地搶佔,而不管它在做什麼。基本上,儘快 作爲一個更高優先級的線程想運行,它的確如此。這就是所謂的搶佔多任務