-3

我正在阅读有关 java Thread 的主题

还有一个例子:

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
..............

问题是什么?

任何人都可以为我解释一下吗?

4

4 回答 4

4

作者的全部观点是不同线程之间的任务顺序是不可预测的。他打印了一个可能的输出序列,但还有很多很多其他的可能。

于 2013-09-24T08:52:34.100 回答
1

除了已经解释过的输出之外,我必须补充一点,您正在阅读的这本书似乎不是一个很好的学习资源。它教导:

  1. extend Thread,一个臭名昭著的坏习惯;

  2. 在实例上调用wait和调用——另一种已知的、记录在案的不良做法。notifyThread

  3. 首先使用waitandnotify机制,它大部分已被更方便和更简单的java.util.concurrent工具所取代,例如CountDownLatch,SemaphorePhaser.

于 2013-09-24T09:12:49.487 回答
0

唯一奇怪的是有 6 个连续的“放置消息”,这似乎是不可能的,因为最大队列大小为 5。

但这是因为代码序列

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

是 - 当然 - 不是原子的,并且已被线程切换中断。

顺便说一句 - 始终使用notifyAll()而不是notify.

于 2013-09-24T09:03:35.950 回答
0

您的输出版本是正确的。因为没有“put message”就不可能“得到消息”。我的意思是,如果队列中没有消息,那么如何检索消息。在他的示例中,开发人员可能给出了示例输出,这不是实际的代码运行输出,而是自己制作的示例。

请记住:[直到特定行的“收到消息”总数]将始终为 <= [直到该行的“发送消息”总数]

于 2013-09-24T08:57:21.277 回答