一个多线程REST API客户端的设计

3
我正在开发一个程序,接收主题的搜索请求,通过调用纽约时报API来获取与该主题相关的文章,然后再通过 Twitter API 获取提到这些文章的推文,并最终处理结果并将其返回。
我必须将此程序设计成多线程的。 我考虑使用带有固定大小线程池的 ExecutorService。 因此,每个传入的搜索请求都将由单独的线程处理。 我还使用 Callable 接口提交任务。 实现 Callable 的类执行 API 处理(进行 API 请求/响应)。 最后,结果由 Future 获取并作为输出显示。 这适用于每个传入的请求。
这样说清楚了吗? 或者有更好的方法吗?
注:我正在本地计算机上运行此程序,从命令行界面接收数据。

什么服务器应用程序? - Amir Raminfar
2个回答

5
如果这是一个Web应用程序,它默认是多线程的。如果不是,您仍然可以将其部署在Servlet容器上,这将是有益的。线程池由底层容器(例如Tomcat)提供。每个请求都由单独的线程服务。
唯一需要注意的事项是:
  • 不要使用synchronized
  • 清理任何使用的ThreadLocal变量

这不是一个网络应用程序。我正在本地机器上运行它,从CLI接受数据。但我仍然想让它支持多线程。 - gofeddy
1
为什么不在Servlet容器上运行它? - Bozho
我想最终会考虑这个选项。在那之前,我试图看看是否可以通过java.util.concurrent功能集实现某些东西。 - gofeddy

2
我建议先确保工作流程正确,然后进行分析,找出瓶颈所在,并尝试确定并发执行(线程 != 并发或异步执行)可以帮助你的地方。使用多个执行线程来饱和CPU、网络或磁盘I/O不会使事情变得更快,通常会损害性能,特别是在超线程Intel CPU上。
然后我会更关注如何使其非阻塞和异步化,而不是让它变成多线程。阻塞任务(串行化)完全抵消了使用线程使事情并发的任何好处。
如果任务仍然在工作流程中串行化,那么多线程并不能神奇地使其运行更快或更有效率。相反,如果您没有正确处理消息传递和异步内容,则可能会使事情变得更慢且效率更低。
此外,如果您正在顶级Core i7笔记本电脑上运行此应用程序,则只会获得4个真实线程(4个超线程通常会使CPU绑定应用程序变得更糟),并且尝试使事情按序发生,然后再将它们放回可能不会带来任何真正的收益,但会增加很多复杂性。在拥有更多核心的服务器上,情况可能不同,在笔记本电脑上,线程不会带来太多好处。 "并发很容易,正确地进行并发非常困难!" - 引用我的合气道老师的话。

不知道是否使用Node.JS是一个简单异步解决方案的好主意... - beny23
@Jarrod Roberson: "四个超线程通常会使CPU密集型应用程序变得更糟" [sic]... 而且 "在笔记本电脑上,线程不会让你得到太多" [sic]... 关于第一个引用,链接将非常受欢迎。关于第二个引用,我多次目睹了完全相反的情况:当我使用生产者/消费者方案来处理数据时,当适应消费者线程数到CPU数量时,我获得了更好的吞吐量(例如,在旧的Core 2 Duo Mac笔记本电脑上已经明显)。您真的在提倡在这个多核CPU的时代采用单线程的生产者/消费者模式吗? - TacticalCoder
@TacticalCoder 你在自说自话,我从未说过你所争论的任何事情。但就你的观点而言,如果我有一个序列化的进程和工作流程,使用多个线程将没有负面影响,甚至从来没有积极的影响。在i7上编译,线程=8比线程=4要慢得多。上下文切换和缓存失效非常恶化,特别是在Windows上! - user177800
@TacticalCoder,你对“threads = 1通常会影响性能”的错误解释是你写了我没有说过的东西,并且断章取义,缺乏理解。在上下文中,我说4个线程可以比8个线程更快25%或更多,特别是在一个CPU绑定的应用程序中,使用8个线程上下文来饱和CPU可能会很糟糕,简单明了。你可以随意解读,但我没有说过任何你正在解释的话,简单明了。 - user177800
以防有人误解上面的内容(就像我一样):不要认为多线程编程很难,所以不值得去做,也不要认为使用多个线程会减慢应用程序的速度(我仍然认为上面的答案暗示了这一点)。例如,如果你想在Core i7上编译一个大型软件,只使用i7上的一个线程将非常缓慢。使用四个线程将带来400%的加速。 - TacticalCoder
显示剩余2条评论

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