如何根据生产者线程状态停止使用者线程

时间:2014-03-04 04:10:13

标签: java multithreading

我需要实现一个消费者生产者示例。这是一个简单的程序,我修改了一下,但我不确定它是否存在潜在的问题。如果有人能帮助我改进它,我将不胜感激。我的主要 现在的问题是我不知道如何在生产者完成后停止消费者。

我尝试过以下代码,但不推荐使用stop(),它也不起作用:

    if (!producer.isAlive()) {
            consumer.stop();
    }

ProducerConsumer.java:

    import java.util.Vector;

    public class ProducerConsumer {
        public static void main(String[] args) {
            int size = 5;
            Vector<Integer> sQ = new Vector<Integer>(size);
            Thread consumer = new Thread(new Consumer(sQ, size));
            Thread producer = new Thread(new Producer(sQ, size));
            consumer.start();
            producer.start();

            if (!producer.isAlive()) {
                consumer.stop();
            }
        }
    }

    class Consumer implements Runnable {
        Vector<Integer> sQ = new Vector<Integer>();
        int size;

        public Consumer(Vector<Integer> sQ, int size) {
            this.sQ = sQ;
            this.size = size;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    System.out.println("Consuming element: " + consume());;
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }

        private int consume() throws InterruptedException {
            synchronized (sQ) {

                while (sQ.isEmpty()) {
                    System.out.println("The queue is empty and "
                            + Thread.currentThread().getName() + " has to wait."
                            + "size is: " + sQ.size());
                    sQ.wait();
                }

                sQ.notifyAll();
                return sQ.remove(0);
            }

        }

    }

    class Producer implements Runnable {
        Vector<Integer> sQ = new Vector<Integer>();
        int size;

        public Producer(Vector<Integer> sQ, int size) {
            this.sQ = sQ;
            this.size = size;
        }

        @Override
        public void run() {
            for (int i = 0; i < 12; ++i) {
                try {
                    produce(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        private void produce(int i) throws InterruptedException {

            synchronized (sQ) {
                while (sQ.size() == size) {
                    System.out.println("The queue is full and "
                            + Thread.currentThread().getName() + " has to wait."
                            + "size is: " + sQ.size());
                    sQ.wait();
                }

                sQ.add(i);
                sQ.notify();
            }

        }
    }

2 个答案:

答案 0 :(得分:2)

建议的方法通常是在需要终止然后循环finished的线程上设置布尔标志(while(!finished)或类似)。 (请注意,该标志通常需要为volatile,以便线程看到更改。)如果预期线程阻塞,则可以interrupt()重新启动其等待循环。

但是,您采取的整体方法似乎已经过时了。 BlockingQueue实现专门用于简化生产者 - 消费者实现,并且可以通过使用Executor并在它们进入时触发任务而不是手动排队和轮询来更有效地处理许多此类问题

答案 1 :(得分:0)

使用CountdownLatch。这允许您等待它在一个线程中降低并实际从另一个线程降低它。它是线程安全的,专为此用例而设计。

如果您要使用布尔值,如其中一个提交中所建议的那样,请使用AtomicBoolean。

通常,避免使用诸如synchronized或volatile之类的语言原语,而是使用java.concurrent包提供的更高级别的结构。如果你要进入低级别,你需要对语义有一个坚定的理解。

如果您想重用而不是重新发明,您可能希望使用我的并发处理迭代:https://github.com/jillesvangurp/iterables-support/blob/master/src/main/java/com/jillesvangurp/iterables/ConcurrentProcessingIterable.java

您只需预测输入,它会根据您的需要同时生成带有多个线程的输出。