有太多线程吗?

问题描述 投票:2回答:3

环境:Ubuntu 16.04 - Linux,使用GCC编译C ++ 11。软件不需要跨平台 - 但在其任务中是高效的,并且是一个优秀的守护进程。

我目前有一个简单的应用程序,它基本上充当第三方服务和websocket连接之间的中介。所以用户通过websocket连接我的服务与所述第三方服务交谈。

| End-User |  <-C1-> | My Application | <-C2-> | 3rd Party Service |

我的应用程序目前有2个主线程:

  1. 线程1 - 收听websocket连接,每当收到消息时,它会将包含消息的对象和请求所述消息的websocket连接推送到fifo任务队列。
  2. 线程2 - 遍历消息队列,弹出消息并对其进行处理

问题是线程1非常快,并且可以轻松处理100个websocket连接。线程2有时阻塞任务并且可能很慢,因为所述第三方服务的某些队列项处理需要一段时间。这意味着,如果用户A确实请求1(需要5秒钟响应),而后来用户B发出请求2,则必须等待用户A的请求1完成,即使请求2花费不到1毫秒。

我建议的解决方案是:

  • 线程1 - WebSocket连接侦听器
  • 线程2任务委托人
  • 线程3 - 100 - 任务工作者

线程1可以轻松处理100个websocket连接,并且每个连接可以请求任务可能需要1ms到1分钟。所有线程3 - 100都在睡觉。这么多线程的原因是因为如果有50-60个连接都会产生不同的长时间运行请求,那么这些耗时的调用中的每一个只会阻塞一个线程,其他线程仍可以自由地在队列上工作,并且做其他任务。

我知道切换线程是一个密集型操作,但我不知道除了mulithreading之外的任何其他方法。

我用单个线程解决了同样的问题 - 但问题是服务器在等待第三方服务时阻止处理任何websocket消息。所以我把它碰到了两个线程 - 一个用于websocket,另一个用于处理任务队列。但现在问题是任务队列上的单个工作人员很慢,因为它正在顺序处理阻塞IO操作。

这听起来像是一个糟糕的设计理念吗?对最佳实践的任何想法?

c++ c multithreading g++
3个回答
6
投票

有太多线程吗?

100个主题

如果在任何桌面/服务器上有点不理想,应该没问题。我有一台笔记本电脑拒绝在一个过程中约2000个线程后继续。

其他策略

为了获得最大吞吐量,常见的设计决策是每个CPU核心约1个线程,并采用基于异步电路的设计。

一些例子:

  • libuv
  • 提高:: ASIO
  • libdispatch
  • win32异步操作

3
投票

“有太多线程吗?” - 是的线程消耗您可能耗尽的系统资源。线程需要安排;需要内核的工作以及CPU上的时间(即使他们希望什么都不做)。更多线程增加了复杂性,使您的程序更难以推理并且更难调试。

确实存在太多线程 - 永远不会创建超出您需要的东西/对您的程序有意义的东西。


0
投票

最简单也可能是最有效的方法是使用线程池。线程池通常由OS(或.NET等底层平台)实现,并针对最佳吞吐量进行了优化。线程池持续监视发送到线程池的任务的执行效率,并在吞吐量下降时动态创建新线程,或者如果线程已经做了一段时间,则会释放线程。何时创建和释放线程的算法非常复杂,对于大多数用途,线程池是如何将工作负载拆分为多个线程的最有效方法。

Windows和Linux都支持线程池,但由于您使用的是C ++ 11,因此您还可以使用可以通过调用函数std::async使用的标准C ++库线程池。这是一些不错的sample

© www.soinside.com 2019 - 2024. All rights reserved.