1

我有一个充当服务器的类对象。它从任何地方接收请求并将请求推送到其请求队列(Producer)中。现在有一个消费者线程正在运行,它从请求队列中弹出请求,并根据请求调用适当的类方法来提供请求。现在,队列中的请求的消耗和适当功能的启动正在以同步方式执行。我想要的是消费者线程从队列中弹出一个请求并以异步方式启动适当的函数,以便消费者可以立即从队列中弹出下一个请求。

我尝试过的一种解决方案是消费者从队列中弹出一个请求,并boost::thread在新线程中创建并启动适当的函数。我已经保存了线程指针,std::vector也试过了boost::thread_group。到现在为止还挺好。但是这个解决方案有一个问题。

一旦我提供了超过 150 个请求,就会有更多 150 个线程,之后 pthread不会创建新线程并给出错误"pthread_create: Resource temporarily unavailable",我相信这意味着当前进程的堆栈已经用完,因此无法创建新线程。

问题 #1我的请求处理程序不包含while (1),它们只是在做一些工作并退出并且根本不等待任何东西,这就是为什么我期望我的初始线程已经完成它们的处理并退出线程处理程序函数。考虑到这一点,如果线程已完成处理并退出,它不应该从堆栈中清理掉它的东西吗?

这个问题的一个解决方案是我可以设置线程的堆栈大小,但是在说 1000 个线程之后仍然会引发这个错误。

所以我的要求是我必须在一段时间后清理完成的线程(即当线程指针向量超过 100 或每 1 分钟或类似的时间后)。

问题 #2除了像我上面提到的那样启动新线程之外,我应该尝试的其他异步函数调用机制是什么。boost::function+是boost::bind异步的吗?这是解决我提到的情况的好方法吗?假设我的系统应该 24/7/365 在线并且每天收到 >1000 个请求。


更新 #1 所以我在我的设计中发现了一个问题。我在问题 #1 中提到我的请求处理程序只包含我发现不正确的普通调用。它是从服务器同步下载文件,本质上是一个阻塞操作。我应该异步下载文件。

如果请求处理程序没有执行任何阻塞操作,则创建底层系统无法同时处理的线程是没有用的。

因此,正如 Alex 提到的那样,拥有多个消费者线程(我认为 5 个就足够了)从队列中弹出一个请求并进行异步文件下载将解决我的问题。

4

2 回答 2

1

一种解决方案是拥有多个消费者线程,每个线程从队列中弹出一个工作项并同步处理它。它使您能够管理并发(避免过度订阅),同时仍然一次处理多个项目。您还消除了在每个项目上启动新线程的开销,我预测这是您的瓶颈之一。

您应该确保您的队列是为多个消费者设计的。

从未使用过此实现,但线程池可能会有所帮助。

于 2013-01-21T13:12:39.717 回答
1

您已经使用了 Boost 并下载了文件。因此,将 Boost.Asio 用于网络和所有其他多线程/异步相关的东西,比如中央调度程序,这将是很自然的。

首先,我建议创建一个线程池并在它们上运行 Asio 调度程序:就像这里。使用 Asio 异步网络下载文件:此处的示例。下载文件时,只需处理它。

这种方法非常可扩展,您不必担心异步网络或多线程同步(相当棘手的事情)。Boost.Asio 提供了很好的例子来实现这一点。

于 2013-01-21T14:21:59.170 回答