单线程池 vs 每个任务一个线程池

4
我想在Java中使用并发来向在线API发送请求,下载和解析响应文档,并将结果数据加载到数据库中。
在一个线程池中,每个线程都请求、解析和加载,这种方式是标准的吗?换句话说,只有一个类实现了Runnable。或者说,拥有三个不同的线程池更有效率,第一个线程池用于请求并将请求推送到队列中,第二个线程池从第一个队列中轮询,进行解析,并将解析后的数据推送到第二个队列,最后第三个线程池从第二个队列中轮询数据,并加载到数据库中。在这种情况下,我会编写三个不同的实现了Runnable的类。

2
使用流水线模型(即三个池),您可能需要找出池大小的最佳比例,或动态调整池大小以确保它们平衡。也就是说,您需要问自己类似这样的问题:“如果我有10个并发的“下载”线程,我需要多少个并发的“解析”线程才能确保下载-解析队列保持相对恒定的大小? - ArjunShankar
3个回答

8
您需要考虑哪些处理部分可以受益于并行处理。在线API通信很可能是候选项,因为涉及套接字和网络等待。与此类似的是DB交互。如果有多个可用CPU核心,多线程解析可能只会提高性能。
将整个过程拆分为3个单独的类肯定会增加内聚性,这意味着每个类的责任更少,这是一件好事。另一方面,使这些类中的每一个成为Runnable并拥有几个队列将增加应用程序的复杂性(可能是不必要的)。
我建议创建3个单独的类,但不要让它们成为Runnable。然后制作一个Runnable,该Runnable包含并协调3个类,即一个单线程池。如果您发现这似乎不够快(并经过一些分析),请尝试将Runnable分成2个线程池:下载和解析以及DB访问。
重点是,从简单开始,并根据需要添加复杂性。

2
重要的一点需要考虑:处理的顺序是否重要?也就是说,第一个下载请求的解析结果在第二个请求的结果之前加载到数据库中是否很重要?
如果是这样,您确实需要队列(或类似的东西),每个任务一个队列。实际上,需要三个单线程池(或使用ExecutorService)。
如果不是,@Brady提出了很好的观点。与他不同的是,我可能会将所有三个类都设置为Runnable,但这并不意味着您必须使用三个队列,您仍然可以尝试使用单个池,并进行性能分析以查看它的工作方式。

0

我不相信有一个标准的方法,这取决于你的需求。

如果你只是写一些快速而简单的东西,那么最好只用一个池。

如果你想要更强大的可靠性和需要恢复功能,那么你可以选择多个池。例如,如果你持久化响应并且你的应用程序崩溃了,那么当它重新启动时,你可以重新排队响应,而无需再次获取它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接