2013-09-24 85 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