生产消费者

时间:2015-06-05 18:48:05

标签: java multithreading concurrency

我尝试使用wait()notifyAll()方法实施生产者消费者模式,但存在一些问题。所以我的代码就是下一个。

主要课程

import java.util.LinkedList;
import java.util.List;

public class TestThread {

    public static void main(String[] args) {
        final List testQueue = new LinkedList();

        final Producer producer = new Producer(testQueue);
        final Consumer consumer = new Consumer(testQueue);

        Runnable prodThread = new Runnable() {
            @Override
            public void run() {
                producer.putMessages();
            }
        };
        Runnable consThread = new Runnable() {
            @Override
            public void run() {
                consumer.readMessages();
            }
        };

        (new Thread(prodThread)).start();
        (new Thread(consThread)).start();
    }
}

制作课程

class Producer {
    private final List queue;

    public Producer(List queue) {
        this.queue = queue;
    }

    public void putMessages() {
        // Add batch of messages to queue
        for (int t = 1; t <= 2; t++) {
            synchronized (queue) {
                try {
                    // if size of queue is more then 2, then wait
                    while (queue.size() > 1) {
                        System.out.println("Producer: Queue is full! Size of queue is " + queue.size() +", so Producer is waiting...");
                        queue.wait();
                        // Consumer could start own work here
                    }
                    for (int i = 0; i < 2; i ++) {
                        queue.add("String" + (i+1)*t);
                        System.out.println("Producer: Message -" + queue.get(i) + "- was added to queue...");
                    }
                    System.out.println("Producer added batch of messages, let's notify our Consumer...");
                    queue.notifyAll(); // consumer thread should be in wait set
                }
                catch(Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

消费者类

class Consumer {
    private final List queue;

    public Consumer(List queue) {
        this.queue = queue;
    }

    public void readMessages() {
        synchronized (queue) {
            try {
                //while queue is empty let's wait - producer will get processor time in this case
                while (queue.isEmpty()) {
                    System.out.println("Consumer: Queue is empty! Nothing to read, so Consumer is waiting...");
                    queue.wait();
                }
                for (int k = 0; k < queue.size(); k++) {
                    System.out.println("Consumer: Read messages from queue -" + queue.get(k) + " -");
                }
                //clean our queue
                queue.removeAll(queue);
                if (queue.isEmpty()) {
                    System.out.println("Consumer finished reading, notify Producer that queue is empty, please start adding new messages for me!");
                    queue.notifyAll();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

程序执行的结果:

Consumer: Queue is empty! Nothing to read, so Consumer is waiting...
Producer: Message -String1- was added to queue...
Producer: Message -String2- was added to queue...
Producer added batch of messages, let's notify our Consumer...
Consumer: Read messages from queue -String1 -
Consumer: Read messages from queue -String2 -
Consumer finished reading, notify Producer that queue is empty, please start adding new messages for me!
Producer: Message -String2- was added to queue...
Producer: Message -String4- was added to queue...
Producer added batch of messages, let's notify our Consumer...

根据我的代码,我希望消费者读取来自制作人String2String4的最后消息并打印结果。但是没有发生,我的代码出了什么问题?

1 个答案:

答案 0 :(得分:1)

您运行消费者的主题按预期进入readMessages()。这里没有循环机制,因此在消耗前两条消息之后它继续执行并退出方法。

您的制作人通知所有感兴趣的线程队列中有消息,但消费者没有收听。消费者存在的线程已经终止。