c++中的线程池设计
thread pool design in C++
我不知道如何把这个问题放在这个论坛上,我问的任何方式,希望得到一些输入。
我正在为我的项目写线程池。我有以下设计。
-
我正在维护线程向量
std::vector<ThreadWrapper <threadFuncParam>* > m_vecThreads;
-
并将线程推入列表
m_vecThreads.push_back(pThreadWrapper);
-
当新的请求来了,我采取线程池如下
if(!m_vecThreads.empty() ) { ThreadWrapper <threadFuncParam>* pWrapper = m_vecThreads.back(); m_vecThreads.pop_back(); //... Awake threadd }
-
当线程任务完成时,它被推回线程池。
现在,虽然优雅的关闭,我已经优雅地停止线程现在与上面的设计,我面临的问题,我如何能停止线程,因为在矢量容器我从矢量弹出时请求服务,所以我失去了指针,直到服务完成。是否有更好的我可以做到这一点或处理这种情况像地图或其他容器是由标准c++支持?
另一个问题是
在关机期间,我有一个场景线程正在做进程,在我的情况下,从数据库读取可能需要时间,所以我不能等到它完成我想要回复客户端等待线程正在处理的请求,我要杀死那个值是坏的。
谢谢!
如果仍然需要访问池中分发的内容,则应该将这些项存储在"used"容器中。
然而,此时,您正在共享指针,因此您应该使用shared_ptr并传递weak_ptr,这样线程也可以被删除,并且用户没有悬垂指针
使用过的项的最佳容器是set,这样可以很容易地找到并删除返回的线程。
要解决你的第一个问题,把它推到另一个向量上,比如m_vecBusyThreads
,当它完成时,把它从那里拿走(注意,你必须有一些机制来搜索完成的线程)。
对于你的第二个问题,最干净的解决方案是加入每个线程,直到它有"关闭",任何其他方法最终可能会有一些不希望的副作用(特别是,例如,如果它连接到一个数据库等)现在,你有繁忙的容器,迭代通过告诉每个关闭,然后迭代通过你的每个空闲容器,关闭和加入每个线程。然后返回繁忙的容器并尝试连接每个线程。这可以给繁忙的线程一点时间来干净地关闭。
boost::threads支持这种中断点的概念,其想法是您可以在这些点中的任何一个中断线程,然而有些调用是不可中断的(通常是阻塞调用),您需要找到停止每种类型的最佳方法(例如socket读取可能是发送一个虚拟数据包等)
我已经在C中完成了它,因此解决方案不是"c++"式的,但我使用了两个数组:一个包含线程,另一个包含已使用/未使用的表示(~boolean)。
我将是这样的:
pthread_t[INITIAL_SIZE] thread_pool;
boolean[INITIAL_SIZE] threads_availability;
int first_available = 0;
pthread_t * get_thread() {
int ind = 0;
if (first_available<=INITIAL_SIZE) {
ind = first_available;
// find the next available spot
for (first_available; first_available < INITIAL_SIZE && threads_availability[first_available]; first_available++);
threads_availability[ind] = 0;
return thread_pool[ind];
}
}
void put_thread(pthread_t* thethread)
{
int i = 0;
pthread_t *it = thread_pool;
while (!pthread_equals(it, thethread)) {
it++;
i++;
}
thread_availability[i] = 1;
}
请记住,这是伪代码,这不是最佳的。但这是一个想法。
这不是对你问题的直接回答,因为其他人已经回答了你最初的问题。
我只是想说你可以看看boost::asio和/或boost::thread。我可能会选择boost::asio,因为它具有基于计时器和诸如此类的异步操作所需的一切。你可以使用shared_ptr和boost::enable_shared_from_this来让你的"作业"离开,并在它们完成作业时自动销毁。
的例子:
boost::shared_ptr<async_job> aj( new async_job(
io_, boost::bind(&my_job::handle_completion, shared_from_this(), _1, _2)));
这段代码将在线程池上执行您的自定义async_job (io_是boost::asio::io_service)。当async_job完成并在其上调用handle_completion时,您的'my_job'实例将自动销毁。或者你可以让它存活,如果你在handle_completion中再次执行shared_from_this()。
HTH,亚历克斯
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- c++中的线程池
- 线程之间的布尔停止信号
- 为什么std::async使用同一个线程运行函数
- 用于矢量处理的多个线程
- C++为线程工作动态地分割例程
- 为什么我不能在 while 循环中创建线程?