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