C++中的线程池设计

问题描述:

我不知道如何把这个问题放在这个论坛中,我想问什么,并希望得到一些输入。C++中的线程池设计

我正在为我的项目编写一个线程池。我有以下设计。

  1. 我保持线程std::vector<ThreadWrapper <threadFuncParam>* > m_vecThreads;

  2. 的载体和推动threds到列表m_vecThreads.push_back(pThreadWrapper);

  3. 当新的请求到来时我正在线程池如下

    if(!m_vecThreads.empty()) 
    { 
        ThreadWrapper <threadFuncParam>* pWrapper = m_vecThreads.back(); 
        m_vecThreads.pop_back(); 
        //... Awake threadd 
    } 
    
  4. 当线程工作完成后,它被推回到线程池。

趁现在gracefull关机我有设计优雅现在停止线程上面我面临的问题,我如何能阻止线程在vector容器我从矢量坡平当请求服务,所以我失去了指针直到服务完成。 有没有更好的我可以做到这一点或处理这种情况下,如地图或其他标准C++支持的容器?

另一个问题是

在关闭过程中,我有一个场景线程在这里做在我的情况下,来自这可能需要时间数据库中读取数据的过程,所以我不能等到它是完整的 ,我想送答复客户挂起的请求线程正在处理,我即将杀死该值是不好的。

谢谢!

+0

你有什么没有线程的载体而指针到线程的向量。你如何自己实例化线程,你用'new'手动执行吗?考虑将线程包装存储在另一个容器中,例如'std :: vector >',并将这些线程的地址放入'm_vecThreads'中。 – leftaroundabout

+0

你的“另一个问题”应该作为一个真正的其他问题被问及+你不清楚你的问题是什么。 – stefaanv

为了解决你的第一个问题,把它推到另一个向量上,比如m_vecBusyThreads,当它完成时,把它拿下来(注意,你必须有一些机制来搜索完成的线程)。对于你的第二个问题,最干净的解决方案是加入每个线程,直到它“关闭”,任何其他方法可能最终产生一些不良副作用(尤其是如果它连接到数据库等)。你有繁忙的容器,遍历告诉每个关闭,然后遍历每个免费的容器,关闭并加入每个线程。然后返回繁忙的容器并尝试加入每个线程。这可能会给繁忙线程一点时间关闭干净。

boost :: threads支持这种中断点的概念,其思想是你可以在任何这些点上中断一个线程,但是有些调用是不可中断的(通常是阻塞调用),你需要找到最好的方法以停止每种类型(例如套接字读取可能会发送一个虚拟数据包等)

我已经在C中完成了,所以解决方案不是“C++”ish,但我使用了两个数组:一个包含线程,另一个包含used/unused(〜布尔)的表示。

我会是这样的:

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; 
} 

请记住,这是伪代码,这是不是最佳的。 但这是一个想法。

+0

虽然在将一个使用过的物品放入另一个容器中存在一些开销,但对于较大的池,此解决方案可能会相当昂贵。 – stefaanv

如果您仍然需要访问您从池中传出的内容,则应将这些项目存储在“已用”容器中。
然而,在那一刻,你分享你的指针,所以你应该使用的shared_ptr,并传递出的weak_ptr,所以线程也可以删除,用户没有悬空指针

的最佳cointainer使用的项目将是一个集合,因此返回的线程可以很容易地找到并移除。

这不是您的问题的直接答案,因为其他人已经回答了您的原始问题。

我只是想说你可以看看boost :: asio和/或boost :: thread。 我可能会去boost :: asio,因为它拥有基于定时器和whatnot进行异步操作所需的一切。你可以使用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_是提高:: ASIO :: io_service对象)。当async_job完成并调用handle_completion时,您的'my_job'实例将自动销毁。或者,如果您在handle_completion中再次使用shared_from_this(),则可以让它生存。

HTH, 亚历