C ++中的线程池设计

时间:2011-11-25 08:59:28

标签: c++ multithreading

我不知道如何在这个论坛中提出这个问题,无论我问什么,希望得到一些意见。

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

  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. 当线程作业完成后,它会被推回到线程池中。

  5. 现在,当gracefull关闭我现在正在优雅地停止线程与上面的设计我面临的问题我如何停止线程,因为在向量容器中我从向量弹出请求服务,所以我丢失指针,直到服务完成。 有没有更好的我可以做到这一点或处理这种情况,如标准C ++支持的地图或其他容器?

    另一个问题是

    在关机期间我有一个场景线程正在这里进行处理,在我的情况下从数据库读取这可能需要一些时间,所以我不能等到它完成 我想发送回复客户端的线程正在处理的待处理请求,我即将杀死该值是坏的。

    谢谢!

4 个答案:

答案 0 :(得分:1)

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

使用过的物品的最佳标记是一组,因此可以轻松找到并移除返回的线。

答案 1 :(得分:0)

要解决您的第一个问题,请将其推送到另一个向量,例如m_vecBusyThreads,当它完成后,将其从那里取下(注意,您必须有一些机制来搜索已完成的线程)

对于你的第二个问题,最干净的解决方案是加入每个线程,直到它“关闭”,任何其他方法可能最终会产生一些不良的副作用(例如,如果它连接到数据库等),那么你拥有繁忙的容器,迭代告诉每个人关闭,然后遍历每个空闲容器,关闭并加入每个线程。然后返回繁忙的容器并尝试加入每个线程。这可能会让繁忙的线程有一点时间干净地关闭。

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

答案 2 :(得分:0)

我已经在C中完成了,所以解决方案不是“C ++”ish,但是我使用了两个数组:一个包含线程,另一个包含used / unused(~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;
}

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

答案 3 :(得分:0)

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

我只想说你可以查看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, 亚历