我正在阅读一些有关Java生产者使用者实现的信息。 示例中的大多数在线代码都通过以下基本对象显示了解决方案:
用作数据管道的阻塞队列
n个已将消息推送到队列中的生产者
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());
}
}
答案 0 :(得分:0)
您的方法没有什么问题,只是不明显Executors.newFixedThreadPool().
创建的池中使用了什么队列?如果任务数量变得可观,您确定无法获得RejectedExecutionException
吗?
因此,最好使用具有预定义大小的任务队列的新的显式创建。
查看Executors.newFixedThreadPool(int)
的源代码。
答案 1 :(得分:0)
实际上,最好在生产者-消费者应用程序中使用线程池。来自Java Concurrency in Practice:
Executor
基于生产者-消费者模式,其中活动 提交任务的是生产者( 完成),执行任务的线程是使用者(使用者 这些工作单元)。使用执行器通常是最简单的方法 在您的应用程序中实现生产者-消费者设计。
选择实现时应考虑的事项:
Queue
最适合这项工作?ThreadPool
损坏或关闭会怎样?