3

我的应用程序需要一个线程池,并且我想尽可能地依赖标准(C++11 或 boost)的东西。我意识到有一个非官方的(!)boost线程池类,它基本上解决了我需要的东西,但是我宁愿避免它,因为它不在boost库本身 - 为什么它仍然不在核心库中很多年?

在此页面和其他地方的一些帖子中,人们建议使用 boost::asio 来实现类似线程池的行为。乍一看,这看起来像是我想做的,但是我发现我所看到的所有实现都无法加入当前活动的任务,这使得它对我的应用程序毫无用处。为了执行加入,它们向所有线程发送停止信号,然后加入它们。但是,这完全抵消了线程池在我的用例中的优势,因为这使得新任务需要创建新线程。

我想做的是:

ThreadPool pool(4);
for (...)
{
    for (int i=0;i<something;i++)
        pool.pushTask(...);
    pool.join();
    // do something with the results
}

任何人都可以提出解决方案(除了使用 sourceforge 上现有的非官方线程池)?C ++ 11或核心提升中有什么可以帮助我吗?

4

4 回答 4

3

乍一看,这看起来像是我想做的,但是我发现我所看到的所有实现都无法加入当前活动的任务,这使得它对我的应用程序毫无用处。为了执行加入,它们向所有线程发送停止信号,然后加入它们。但是,这完全抵消了线程池在我的用例中的优势,因为这使得新任务需要创建新线程。

我想你可能误解了 asio 的例子:

IIRC(已经有一段时间了)在线程池中运行的每个线程都已调用io_service::run,这意味着每个线程实际上都有一个事件循环和一个调度程序。然后让 asio 完成任务,您可以io_service使用 io_service::post 方法将任务发布到 io_service::post 方法,而 asio 的调度机制会负责其余的工作。只要您不调用io_service::stop,线程池将继续使用与您开始运行一样多的线程运行(假设每个线程都有工作要做或已分配一个io_service::work对象)。

所以你不需要为新任务创建新线程,这会违背线程池的概念。

于 2012-10-24T18:49:15.213 回答
1

让每个任务类派生自具有“OnCompletion(task)”方法/事件的任务。然后线程池线程可以在调用任务的主 run() 方法后调用它。

等待一个任务完成就很容易了。OnCompletion() 可以执行任何所需的操作来向发起线程发出信号、向 condvar 发出信号、将任务排队到生产者-消费者队列、调用 SendMessage/PostMessage API、Invoke/BeginInvoke 等等。

如果一个起始线程需要等待多个任务全部完成,您可以扩展上述内容并向池发出单个“等待任务”。等待任务有自己的 OnCompletion 来传达其他任务的完成情况,并有一个线程安全的“任务计数器”(原子操作或锁),设置为要发出的“主要”任务的数量。等待任务首先发布到池中,运行它的线程在等待任务中的私有“allDone”condvar 上等待。然后将“主要”任务发送到池,并将它们的 OnCompletion 设置为调用等待任务的方法,该方法将任务计数器递减到零。当任务计数器达到零时,实现这一点的线程向 allDone condvar 发出信号。等待任务 OnCompletion 然后运行,从而发出所有主要任务完成的信号。

这种机制不需要线程池线程的持续创建/终止/加入/删除,对原始任务需要如何发出信号没有任何限制,并且您可以根据需要发布任意数量的此类任务组。但是,您应该注意,每个等待任务都会阻塞一个线程池线程,因此请确保在池中创建一些额外的线程(通常没有任何问题)。

于 2012-10-14T10:31:57.687 回答
1

这似乎是boost::futures的工作。文档中的示例似乎准确地展示了您想要做什么。

于 2012-10-24T17:22:15.303 回答
0

加入一个线程意味着停止它直到它停止,如果它停止并且你想给它分配一个新任务,你必须创建一个新线程。因此,在您的情况下,您应该等待一个条件(例如boost::condition_variable)来指示任务结束。因此,使用这种技术很容易使用boost::asioand来实现它boost::condition_variable。每个线程调用boost::asio::io_service::run和任务将在不同的线程上安排和执行,最后,每个任务将设置一个boost::condition_variable或事件减量 astd::atomic以指示作业结束!这真的很容易,不是吗?

于 2012-10-14T09:40:23.793 回答