【问题标题】:Which Java blocking queue is best for multiple producer and single or multiple consumers scenarios?哪个 Java 阻塞队列最适合多个生产者和单个或多个消费者场景?
【发布时间】:2010-11-17 15:24:06
【问题描述】:

哪个 Java 阻塞队列最适合多生产者和单个或多个消费者场景?

我正在使用 LinkedBlockingQueue 进行测试,但出现 OutOfMemoryError 异常。

我正在努力实现以下目标。

  1. 生产者创建一个对象并放入队列中。
  2. 消费者从队列中抓取数据并插入数据库。会有 400 个生产者,我可以根据需要调整消费者。

如果有任何想法,请告诉我。

更新

Producer : 它应该监听 Server Socket。它从套接字读取数据并构造对象(域对象)并放入队列中。

消费者:从队列中取出对象并插入数据库(支持 Hiberante 和连接池)

这是我的真实环境。流程应该能够处理至少 200 条记录/秒。我正在测试流程的可扩展性以及如何改进它。我希望这会提供更好的想法。

有用的链接:

vmoptions

Monitoring and Managing Java SE 6 Platform Applications

BlockingQueue

【问题讨论】:

    标签: java multithreading queue


    【解决方案1】:

    每个生产者都是一个单独的线程吗?不要忘记每个线程将为其堆栈分配(默认情况下)512k 内存(在您的情况下,仅线程需要 200Mb 的 VM 内存)。您可以通过-Xss 减少此问题。

    或者,您要排队的对象有多大?我不认为您有 queue 问题,而是某种扩展问题 - 例如。生产者的生产速度快于消费者的消费速度。

    【讨论】:

    • 感谢您的意见。我检查了队列的大小增长,它从 80k 增加到 90k 并开始抛出 OutOfMemoryError 错误。队列保持 java 类,它是表的域类,包含 10 个字段。
    • 如果您的域对象大小为(例如)500 字节,那么您的队列将消耗 0.5kb * 90e3 = 45Mb。这不是那么多,真的。所以我会再次查看您的 VM 内存,也许 a) 增加 VM 大小,b) 减小线程堆栈大小。以上是明智的猜测,顺便说一句,不知道您的域对象有多大,或者您的应用程序正在做什么。
    • 感谢您的关注。我将 VM 大小增加到 -vmargs 为 -Xms512m -Xmx1024m。我为生产者(400)配置了睡眠时间 1000 毫秒,为消费者(10)配置了 100 毫秒。现在进程可以处理 400 条记录/秒
    【解决方案2】:

    LinkedBlockingQueue 似乎是解决您问题的最佳选择。我建议您使用开关 -XX:+HeapDumpOnOutOfMemoryError 运行程序并分析转储文件以查看导致问题的原因。这样你就可以更轻松地解决它了。

    【讨论】:

    • 谢谢,我无法获得我将 -XX:+HeapDumpOnOutOfMemoryError 设置为程序参数的转储文件,参考链接 [java.sun.com/javase/6/webnotes/trouble/TSG-VM/html/clopts.html]
    • 是的,我没有正确传递 JVM 选项。现在我得到了文件,但是当我尝试使用 jhat 实用程序执行时,它抛出异常。
    • jhat -version jhat 2.0版(java 1.6.0_11版)
    • jhat java_pid8296.hprof 从 java_pid8296.hprof 读取...创建转储文件 2009 年 8 月 11 日星期二 13:27:50 EST 2009 线程“main”java.lang.OutOfMemoryError 中的异常:Java 堆空间跨度>
    • 我只是想告诉你增加 jhat 工具的内存:)
    【解决方案3】:

    问题不在于您使用哪个Queue 实现,而在于如何解决如果您的消费者跟不上限制生产者的问题。一种可能的解决方案是创建一个具有固定容量的LinkedBlockingQueue,并让您的生产者调用offer(E e),如果队列已满,它将返回false

    另一种可能的解决方案是相应地调整生产者和消费者的数量。

    【讨论】:

    • +1 我同意您的队列似乎没有合理的容量 - 默认值是相当大的 Integer.MAX_VALUE。如果您已将容量设置为合理但仍有问题,请检查您的 Java 堆大小设置 -Xmx 等...
    • 谢谢大家,我不能实时减少生产者的规模,所以我必须处理它。如果我使用报价,我会失去那个对象,不是吗?我正在使用 put() 和 take()。这将根据队列状态等待。我在 Eclipse 运行配置中将 -vmargs 配置为 -Xms512m -Xmx1024m。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    • 2016-09-11
    • 1970-01-01
    相关资源
    最近更新 更多