【问题标题】:Producer consumer using blockingqueue生产者消费者使用阻塞队列
【发布时间】:2015-02-03 18:19:50
【问题描述】:

我已经开始学习线程并使用JDK 5.0中引入的并发包尝试Java中的生产者消费者问题我编写了以下代码:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

class Producer implements Runnable {
    private final BlockingQueue<Integer> objqueue;

    Producer(BlockingQueue<Integer> obj) {
    objqueue = obj;
    }

    @Override
    public void run() {
    int i = 0;
    while (i < 10) {
        try {
            System.out.println("Put : " + i);
            objqueue.put(i);
        } catch (InterruptedException e) {
        }
        i++;
    }
    }
}

class Consumer implements Runnable {
private final BlockingQueue<Integer> objqueue;

Consumer(BlockingQueue<Integer> obj) {
    objqueue = obj;
}

@Override
public void run() {
    while (true) {
        try {
            System.out.println("Got : " + objqueue.take());
        } catch (InterruptedException e) {
        }
    }
}

}

public class PCMain {

public static void main(String[] args) {
    // create shared object
    BlockingQueue<Integer> obj = new LinkedBlockingQueue<Integer>();

    Thread prod = new Thread(new Producer(obj));
    Thread cons = new Thread(new Consumer(obj));

    prod.start();
    cons.start();
}

}

当生产者生产最多 9 个而消费者消耗最多 9 个时,程序没有终止。我应该删除消费者中永远为真的 while 循环吗?

我怎样才能为不止一个生产者和一个消费者做到这一点? 谢谢。

【问题讨论】:

  • 为什么要终止?
  • 当生产者停止生产时,程序不应该终止吗?
  • 好吧,我没有看到 main 方法,所以我们不知道你是如何调用它的,或者你试图停止代码是什么。但总的来说,不,它不会自行停止。
  • 当所有非守护线程停止运行时,程序停止。不是当 1 个非守护线程停止运行时。
  • 不久前我为朋友写了一个示例,我使用了ExecutorService 和明确的shutdown() 调用,所以有很多方法可以做到这一点。因此:需要查看 main 方法。

标签: java multithreading


【解决方案1】:

你有两个线程,一个应该停止一次i == 10。另一个线程虽然处于无限循环中。您需要向消费线程发出应用程序应该结束的信号。查看Poison Pill 作为告诉第二个线程停止的一种方式。

在消费线程完成之前,程序本身不会停止。

【讨论】:

    【解决方案2】:

    删除while循环将导致消费者只消费生产者提供的1个对象。

    最好使用 Executer 框架。它具有线程工厂和线程池。您可以使用它们来实现。

    【讨论】:

    • Executor 框架在这种情况下并没有解决 OP 的问题。 OP 想了解线程和队列。执行器框架的目的主要是隐藏线程和队列。
    【解决方案3】:

    我认为“修复”您的代码的最简单方法是 make the consumer a daemon thread.

    Thread prod = new Thread(new Producer(obj));
    Thread cons = new Thread(new Consumer(obj));
    
    cons.setDaemon( true );
    prod.start();
    cons.start();
    

    这确实不是一个通用的解决方案,而是一个在不方便发出线程停止信号时要牢记的好技巧。

    【讨论】:

    • 不。在 main 方法存在并且 put 线程完成后,程序将立即关闭。如果 i &lt; 10i &lt; 100000 你只会得到少数成功。
    • 不是在main方法之后:生产者也必须退出。但是,是的,线程很棘手,消费者可能不会完全处理输出。也许我会把它作为一个负面的例子......
    • 可以学习,但一般来说是个坏主意。当 JVM 突然终止时,如果消费者正在写入磁盘或与其他进程通信怎么办?最好告诉消费者是时候关闭了,也许还可以通过 interrupt() 来确保它及时收到消息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 2015-09-25
    • 1970-01-01
    • 2014-10-21
    • 2014-02-20
    • 1970-01-01
    • 2021-09-10
    相关资源
    最近更新 更多