2013-12-15 71 views
1

我做了這個樣本,以測試等待/通知功能:等待不超時

public class WaitingTest implements Runnable { 

    Thread b = new Thread(this,"query"); 
    int total=0; 

    public static void main(String[] args){ 
     WaitingTest w = new WaitingTest(); 
    } 

    public WaitingTest(){ 
     b.start(); 
      synchronized(b){ 
       try{ 
        System.out.println("Waiting for b to complete..."); 
        b.wait(10); 
       }catch(InterruptedException e){ 
        e.printStackTrace(); 
       } 
       System.out.println("Total is: " + total); 
      } 

    } 
    @Override 
    public void run(){ 

    synchronized(b){ 
      for(int i=0; i<1000000000 ; i++){ 
       total += i; 
      } 

     } 
    } 
} 

的問題是,我的輸出應該是零,因爲即時通訊通知10ms的等待後,我的線程時間超過它執行其工作。所以,我的輸出應該是零,而不是它的另一個值。我錯過了什麼?

編輯:

public class WaitingTest implements Runnable { 

     Thread b = new Thread(this,"query"); 
     int total=0; 

     public static void main(String[] args){ 
      WaitingTest w = new WaitingTest(); 
     } 

     public WaitingTest(){ 
      b.start(); 
       synchronized(b){ 
        try{ 
         System.out.println("Waiting for b to complete..."); 
         b.wait(); 
        }catch(InterruptedException e){ 
         e.printStackTrace(); 
        } 
        System.out.println("Total is: " + total); 
       } 

     } 
     @Override 
     public void run(){ 

     synchronized(b){ 
      b.notify(); 
       for(long i=0; i<100000 ; i++){ 
        total += i; 
       } 

      } 
     } 
    } 
+0

沒有必要添加的主要標籤的稱號。 –

+0

@VictorOliveira在你的EDIT上 - 儘管你現在在循環之前調用b.notify(),但你仍然不能得到零(在打印線程中),因爲你還沒有離開同步塊(在計算線程中) 。 –

回答

1

javadocwait()狀態

這種方法導致當前線程(稱之爲T)將自身 等待設置該對象,然後放棄任何和所有 同步聲明此物體

因此wh帶你做

b.wait(10); 

當前線程釋放它具有​​上b,因此您的其他線程才能獲取它在run()方法從

b.start(); 

total開始增加到來。當10ms結束時,主線程重新獲得b上的鎖定(假設run()完成)並打印出總數。請注意,您的total很可能會溢出。

+0

林不知道如果我得到你,但是,這意味着我的「B」線程正在等待被通知,直到它將不執行任何事情,超時後運行將開始執行一次,並且畢竟它會打印總值? (我知道溢出,但這只是一個在真實項目中應用這個想法的示例) –

+0

@victor這一切都取決於線程調度程序,但讓我們舉個例子。你的構造函數被調用,你用'b.start()'開始你的第二個線程。如果該線程首先獲取'b'監視器,則您的'run()'將會完成,因爲您的主線程無法獲取'b'。如果主線程首先獲取'b'監視器,它將打印該消息,調用'wait(10)',放棄對'b'監視器的控制並將其放入'b'監視器的等待區域。您的其他線程將再次完成,此時'b'顯示器可用於拍攝。 –

+0

@Sotirios Delimanolis他只是越來越溢出,這是他的主要問題,而不是線程同步的一部分。 –

0

你得到溢出(你不能總結這些1000000000非負整數並將
結果存儲在一個int中)。總共定義爲。也可撥打b.notify()b.notifyAll()
您的循環後在運行方法完成。
此外,將等待(10)改爲等待(),這將使得打印線程根據需要等待(並非僅10毫秒)而等待計算線程

這是做這個測試的正確方法。

關於線程同步部分,我建議您閱讀例如這些舊文章。

http://www.javaworld.com/article/2074217/java-concurrency/java-101--understanding-java-threads--part-1--introducing-threads-and-runnables.html

http://www.javaworld.com/article/2074318/java-concurrency/java-101--understanding-java-threads--part-2--thread-synchronization.html

http://www.javaworld.com/article/2071214/java-concurrency/java-101--understanding-java-threads--part-3--thread-scheduling-and-wait-notify.html

http://www.javaworld.com/article/2074481/java-concurrency/java-101--understanding-java-threads--part-4---thread-groups--volatility--and-threa.html