【发布时间】:2019-06-19 13:53:50
【问题描述】:
我正在阅读一些关于 Java 中的生产者消费者实现的内容。 大多数在线示例代码显示了具有以下基本对象的解决方案:
用作数据管道的阻塞队列
n 个 Producer 将消息推送到队列中
n 个正在从队列中轮询数据的消费者
通常情况下,消费者会被提交到一个完成实现的线程池。
我调查的另一个选项,几乎没有在线表示,只是将任务作为可运行对象提交到 FixedThreadPool。
在这个实现中,处理消息的业务逻辑在 Runnable 对象的run() 方法中实现。当我们有一条新消息要处理时,我们可以简单地将该类型的新任务提交给FixedThreadPool,然后......就是这样。运行线程的数量由FixedThreadPool 实现与轮询消息的逻辑一起管理,剩下的就是我们用例的业务逻辑。
谁能解释为什么这个解决方案被忽视了?
当 Java 语言已经为我们实现了阻塞队列和轮询时,我们是否需要使用阻塞队列和轮询?
public class ProducerConsumerExample{
private ExecutorService pool;
public ProducerConsumerExample(int numberOfThreads){
this.pool = Executors.newFixedThreadPool(numberOfThreads);
}
public void submit(MessageObject msg){
pool.submit(new MessagePrinter(msg));
}
}
public class MessagePrinter implements Runnable{
private MessageObject msg;
public MessagePrinter(MessageObject msg){
this.msg = msg;
}
@Override
public void run() {
//only need to implement logic that is releavent for our use case
System.out.println("Message recieved " + msg.toString());
}
}
public static void main(String[] args){
ProducerConsumerExample ex = new ProducerConsumerExample(5);
for(int i=0;i<WHATEVER;i++){
ex.submit(new MessageObject());
}
}
【问题讨论】:
-
Re,“......为什么这个解决方案被忽视了?”是什么让你认为它被忽视了?您的问题表明您正在阅读有关生产者/消费者模式的信息。将任务分配给线程池是一种不同的模式。可能有很多问题可以通过任何一种方式解决,但是如果您专门寻找有关生产者/消费者的信息,那么您不应该如果您没有找到有关如何最有效地使用线程池的大量信息,您会感到惊讶。
-
P.S.;使用线程池来启动长时间运行的“消费者”线程有点像将方形钉安装到圆孔中。在这种情况下,您真正要做的是使用线程池代替线程 factory。 Java 标准库定义了一个
ThreadFactory接口,以及获取系统默认ThreadFactory的方法。看看吧!
标签: java multithreading runnable executorservice