我有一个充当服务器的类对象。它从任何地方接收请求并将请求推送到其请求队列(Producer
)中。现在有一个正在运行的消费者线程,它从请求队列中弹出请求,并根据请求调用适当的类方法来提供请求。现在,队列中请求的消耗和适当功能的启动正在以同步方式执行。我想要的是消费者线程从队列中弹出一个请求,并以异步方式启动适当的函数,以便消费者可以立即从队列中弹出下一个请求。
我尝试过的一个解决方案是消费者从队列中弹出一个请求并创建一个 boost::thread
并在新线程中启动适当的函数。我已将线程指针保存在 std::vector
中,并尝试了 boost::thread_group
。到目前为止,一切都很好。但这个解决方案有一个问题。
一旦我提供了超过 150 个请求,就会有超过 150 个线程,之后 pthread
不会创建新线程,并给出错误“pthread_create:资源暂时不可用”
,我认为这意味着当前进程的堆栈已用完,因此无法创建新线程。
问题 #1 我的请求处理程序不包含 while (1)
,它们只是在做一些工作并退出,根本不等待任何事情,那就是为什么我期望我的初始线程已完成处理并从线程处理程序函数中退出。考虑到这一点,如果线程已完成其处理并退出,它是否应该从堆栈中清理其内容?
解决这个问题的一个方法是我可以设置线程的堆栈大小,但是在 1000 个线程之后仍然会引发此错误。
所以我的要求是我必须在一段时间后清理已完成的线程(即当线程指针 vector 超过 100 时或每 1 分钟后或类似的情况)。
问题#2 除了如上所述启动新线程之外,我还应该尝试其他异步函数调用机制。 boost::function
+ boost::bind
是异步的吗?对于我提到的情况,这是一个很好的解决方案吗?假设我的系统应该 24/7/365 在线并且每天接收超过 1000 个请求。
更新#1 所以我发现我的设计存在一个问题。我在问题#1 中提到,我的请求处理程序仅包含普通调用,但我发现这是不正确的。它是从服务器同步下载文件,这本质上是一个阻塞操作。我应该异步下载文件。
如果请求处理程序没有执行任何阻塞操作,则创建底层系统无法同时处理的线程是没有用的。
正如 Alex 提到的,拥有多个消费者线程(我认为 5 个就足够了)来从队列中弹出请求并进行异步文件下载将解决我的问题。
最佳答案
一种解决方案是拥有多个消费者线程,每个线程从队列中弹出一个工作项并同步处理它。它使您能够管理并发(避免过度订阅),同时仍然一次处理多个项目。您还消除了在每个项目上启动新线程的开销,我预测这是您的瓶颈之一。
您应该确保您的队列是为多个消费者设计的。
从未使用过this implementation ,但线程池可能会有所帮助。
关于c++ - C++ 中的异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14439375/