2013-09-24 82 views
-3

我正在閱讀關於java線程的this topicJava線程意外工作

而且還有一個例子:

import java.util.Vector; 

class Producer extends Thread { 

    static final int MAXQUEUE = 5; 
    private Vector messages = new Vector(); 

    @Override 
    public void run() { 
     try { 
      while (true) { 
       putMessage(); 
       //sleep(5000); 
      } 
     } catch (InterruptedException e) { 
     } 
    } 

    private synchronized void putMessage() throws InterruptedException { 
     while (messages.size() == MAXQUEUE) { 
      wait(); 
     } 
     messages.addElement(new java.util.Date().toString()); 
     System.out.println("put message"); 
     notify(); 
     //Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object. 
    } 

    // Called by Consumer 
    public synchronized String getMessage() throws InterruptedException { 
     notify(); 
     while (messages.size() == 0) { 
      wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep. 
     } 
     String message = (String) messages.firstElement(); 
     messages.removeElement(message); 
     return message; 
    } 
} 

class Consumer extends Thread { 

    Producer producer; 

    Consumer(Producer p) { 
     producer = p; 
    } 

    @Override 
    public void run() { 
     try { 
      while (true) { 
       String message = producer.getMessage(); 
       System.out.println("Got message: " + message); 
       //sleep(200); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String args[]) { 
     Producer producer = new Producer(); 
     producer.start(); 
     new Consumer(producer).start(); 
    } 
} 

而筆者說:

A possible output sequence: 
Got message: Fri Dec 02 21:37:21 EST 2011 
put message 
put message 
put message 
put message 
put message 
Got message: Fri Dec 02 21:37:21 EST 2011 
Got message: Fri Dec 02 21:37:21 EST 2011 
Got message: Fri Dec 02 21:37:21 EST 2011 
Got message: Fri Dec 02 21:37:21 EST 2011 
Got message: Fri Dec 02 21:37:21 EST 2011 
put message 
put message 
put message 
put message 
put message 
Got message: Fri Dec 02 21:37:21 EST 2011 
Got message: Fri Dec 02 21:37:21 EST 2011 
Got message: Fri Dec 02 21:37:21 EST 2011 

但是當我運行這段代碼我得到了這樣的結果:

put message 
put message 
put message 
put message 
put message 
put message 
Got message: Tue Sep 24 16:44:59 CST 2013 
Got message: Tue Sep 24 16:45:00 CST 2013 
put message 
Got message: Tue Sep 24 16:45:00 CST 2013 
put message 
Got message: Tue Sep 24 16:45:00 CST 2013 
put message 
.............. 

什麼問題?

任何人都可以爲我解釋嗎?

+0

你指的是什麼問題?輸出看起來類似... – assylias

+0

由於它看起來像作者的輸出符合某種規則。例如,五個「放置消息」,然後五個「獲得消息」,並且「五個」與「MAXQUEUE」相等,那麼如果我錯過任何東西,我真的不知道這是否值得贊成。 – hguser

+0

它不值得讚揚,我同意這一點。 +1 –

回答

4

作者的觀點是不同線程之間的任務順序是不可預知的。他打印可能的輸出序列,但許多其他許多都是可能的。

0

您的版本輸出是正確的。因爲沒有「投入消息」,「得到消息」是不可能的。我的意思是,如果隊列中沒有消息,那麼如何檢索消息。他的例子中的開發人員可能已經給出了不是實際的代碼運行輸出的示例輸出,而是例如自制的。

記住: [總「得到的消息」,直到某一行的計數]永遠是< = [計數總「放消息」到那很行]

0

唯一奇怪的是,有6當然 - - 不原子並且由THR已被中斷,這似乎是不可能的,因爲最大隊列長度爲5

但是,這是因爲代碼序列

producer.getMessage() 
System.out.println("Got message: " + message); 

是連續的「把信息」 ead開關。

順便說一句 - 總是使用notifyAll()而不是notify

1

除了已經解釋過的輸出之外,我還要補充一點,你正在閱讀的書似乎並不是一個很好的學習資源。它教導:

  1. 延長Thread,臭名昭着的壞習慣;在Thread實例—另一個已知,documented不好的做法

  2. 調用waitnotify

  3. 使用waitnotify機制擺在首位,這主要是被取代由更方便,更簡單的java.util.concurrent工具,如CountDownLatchSemaphorePhaser

+0

哦,我沒有注意到他們。順便說一句,你能給我推薦一些資料嗎? – hguser

+1

我沒有很大的喜愛,但Oracle的在線教程應該是相當不錯的。 –

+0

謝謝,我會試一試。 – hguser