首页 > 解决方案 > 使用 FixedThreadPool(s) 和队列的 Java 设计

问题描述

我正在设计一个程序,该程序需要从数据存储中获取结果并将这些结果发布到另一个系统。我正在获取的数据由 UUID 引用,并通过 UUID 链接到其他文档。我将发布很多文档(> 100K 文档),所以我想同时进行。我正在考虑以下设计:

从数据存储中获取文档列表。每个文件将具有:

docId (UUID)
docData (json doc)
type1 (UUID)
type1Data (json)
type2 (UUUID)
type2Data (json)
list<UUID> type3Ids
list of type3 data (json)

我从第一次通话中获得的唯一数据是 docId。我正在考虑将这些文档推送到队列中,并让一组工作人员(获取者)将相关调用返回到数据存储以检索数据。

retrieve the docData from datastore, fill in the type1, type2 and type3 UUIDS
do a batch get to retrieve all the type1, typ2 and type3 docs
Push the results into another queue for posting to other system

第二组工作人员(海报)将从第二个队列中读取每个文档并将结果发布到第二个系统。

我有一个问题,我应该创建 1 个 FixedThreadPool(size X) 还是两个 FixedThreadPool(size X/2)?如果第一个队列中有很多作业,以至于第二个队列在第一个队列为空之前不会启动,是否存在饥饿的危险?

提取器将制作网络煤来与数据库对话,它们似乎更多地受 IO 限制而不是 CPU 限制。张贴者也会进行网络调用,但它们在云中的同一 VPC 中,与我的代码运行的地方相同,因此它们会非常靠近。

标签: javamultithreadingconcurrent.futures

解决方案


阻塞队列

这是一个很正常的模式。

如果您有两个不同的工作要做,请使用两个不同的线程池并使其大小可配置,以便您可以根据需要调整它们的大小/在部署服务器上测试不同的值。

通常使用BlockingQueue具有有限大小(例如,对于任意示例为 1000 个元素)的阻塞队列(内置于 Java 5 及更高版本)。

阻塞队列是线程安全的,所以第一个线程池中的所有内容都尽可能快地写入,第二个线程池中的所有内容都尽可能快地读取。如果队列已满,则仅写入阻塞,如果队列为空,则仅读取阻塞-既好又简单。

您可以调整线程数并重复运行以缩小每个池的最佳配置大小。


推荐阅读