我正在关注Java多线程的视频教程。它介绍了使用Java实现着名的“生产者 - 消费者”问题。
它使用wait()和notifyAll()来确保生产者线程和消费者线程之间的正确通信。
导师故意创建了几个生产者线程而只有一个消费者线程,但他留下了一个未回答的问题:“生产者线程和消费者线程数量相等,总是最好的做法,如果生产者线程多于消费者,那么是问题“。
但是,他没有具体说明问题所在。我个人认为这只是篮子已满的情况。专家可以帮忙吗?感谢。
答案 0 :(得分:6)
您可以拥有任意数量的生产者和任意数量的消费者。
如果生产者生产得太快,队列将填满,直到你遇到内存问题或生产者被迫保持闲置,直到队列中还有一些地方为止。
如果消费者消费太快,他们大部分时间都会闲置。
答案 1 :(得分:2)
最好的做法是拥有相同数量的生产者和 消费者线程
我个人不同意这一点。
有多少生产者以及消费者线程如何完全取决于具体情况。 没有直截了当的规则。
我会告诉你我的情况,
我们有一个程序正在读取CSV文件,从中创建XML并在JMS队列上发布这些XML。这个程序在开始时是单线程的,但是性能没有达到标记。我们发现将消息发送到队列需要花费很多时间。所以我们决定引入多线程。
我们在2个线程中划分逻辑 -
制片人
读取CSV并创建XML
消费
将XML发送到JMS队列。
我们决定只有一个生产者,因为尽管可能,但我们不想为文件打开多个句柄。 另一方面,我们保持创建的消费者线程数量可配置,并且工作正常,我们获得了预期的性能提升。
总而言之,您需要确保生产者线程和消费者线程的速度几乎匹配。否则,如果消费者线程比生产者慢,则记录将堆积在内存(RAM)中,这可能导致OutOfMemory进入极端情况。
答案 2 :(得分:1)
除了制作人效率之外,我没有看到任何问题。如果你有比消费者更多的生产者,并且他们都以相同的速度生产/消费,那么额外的生产者将有效地闲置。
例如,请参阅What's best value for make -j,建议您向n+1
核心提供{{1}}个工作,以便它们始终处于满负荷状态。
答案 3 :(得分:1)
嗯,问题是资源的最佳使用即CPU和内存。正如你正确猜测的那样,篮子将是满的(因此消耗更多的内存),生产者线程将闲置一段时间,直到消费者清空新任务的篮子,这将导致CPU的利用不足。
如果生产者和消费者的数量相等,则线程组(生产者和消费者)将忙于他们的任务,并且篮子也将具有稳定的存储。
现在,太大或太少的生产者/消费者也将成为一个问题。大量的踏板会占用CPU,从而导致其他问题(减速等)。因此总有一个最佳数量取决于机器上可用的硬件资源。
答案 4 :(得分:1)
@JB Nizet很好地总结了这种情况,因为你可能有太多的生产者或太多的消费者。决定因素只是生产者生产的比率与消费者消费的比率。换句话说,如果生产资源需要花费更多的时间而不是消耗它,那么最好是拥有比消费者更多的生产者。但是,如果消耗资源比生产资源需要更多的时间,那么最好有更多的消费者而不是生产者。
导师可能假设消费过程比生产过程更有效,这可能在许多甚至大多数情况下都是正确的,但它不一定是一个好的假设。在设计生产者/消费者系统时,请尽量记住这一点。
答案 5 :(得分:1)
我认为这不取决于消费者/生产者数量,而是取决于速度。您可能有1个消费者可以在10毫秒内处理1个消息,2个生产者可以在100毫秒内生成1个消息。