C++11 中的线程池

2024-01-23

相关问题:

关于 C++11:

  • C++11:std::线程池? https://stackoverflow.com/questions/12993451/c11-stdthread-pooled
  • C++11 中的 async(launch::async) 是否会使线程池过时,以避免昂贵的线程创建? https://stackoverflow.com/questions/14351352/will-asynclaunchasync-in-c11-make-thread-pools-obsolete-for-avoiding-expen

关于升压:

  • C++ boost 线程重用线程 https://stackoverflow.com/questions/2659065/c-boost-thread-reusing-threads
  • boost::thread 并创建它们的池! https://stackoverflow.com/questions/3458397/boostthread-and-creating-a-pool-of-them

我如何获得线程池 to 将任务发送至,而不需要一次又一次地创建和删除它们?这意味着持久线程无需加入即可重新同步。


我的代码如下所示:

namespace {
  std::vector<std::thread> workers;

  int total = 4;
  int arr[4] = {0};

  void each_thread_does(int i) {
    arr[i] += 2;
  }
}

int main(int argc, char *argv[]) {
  for (int i = 0; i < 8; ++i) { // for 8 iterations,
    for (int j = 0; j < 4; ++j) {
      workers.push_back(std::thread(each_thread_does, j));
    }
    for (std::thread &t: workers) {
      if (t.joinable()) {
        t.join();
      }
    }
    arr[4] = std::min_element(arr, arr+4);
  }
  return 0;
}

我不想在每次迭代中创建和加入线程,而是更愿意在每次迭代中将任务发送到我的工作线程,并且只创建一次。


这是改编自我的答案 https://stackoverflow.com/a/32593766/6909078到另一个非常相似的帖子。

让我们构建一个ThreadPool class:

class ThreadPool {
public:
    void Start();
    void QueueJob(const std::function<void()>& job);
    void Stop();
    bool busy();

private:
    void ThreadLoop();

    bool should_terminate = false;           // Tells threads to stop looking for jobs
    std::mutex queue_mutex;                  // Prevents data races to the job queue
    std::condition_variable mutex_condition; // Allows threads to wait on new jobs or termination 
    std::vector<std::thread> threads;
    std::queue<std::function<void()>> jobs;
};
  1. ThreadPool::Start

对于高效的线程池实现,一旦根据以下条件创建了线程num_threads,最好不要 创建新的或销毁旧的(通过加入)。这将会带来性能损失,甚至可能使你的 应用程序比串行版本慢。因此,我们保留了一个可以随时使用的线程池(如果它们 尚未运行作业)。

每个线程都应该运行自己的无限循环,不断等待新任务的获取和运行。

void ThreadPool::Start() {
    const uint32_t num_threads = std::thread::hardware_concurrency(); // Max # of threads the system supports
    for (uint32_t ii = 0; ii < num_threads; ++ii) {
        threads.emplace_back(std::thread(&ThreadPool::ThreadLoop,this))
    }
}
  1. ThreadPool::ThreadLoop

无限循环功能。这是一个while (true)循环等待任务队列打开。

void ThreadPool::ThreadLoop() {
    while (true) {
        std::function<void()> job;
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            mutex_condition.wait(lock, [this] {
                return !jobs.empty() || should_terminate;
            });
            if (should_terminate) {
                return;
            }
            job = jobs.front();
            jobs.pop();
        }
        job();
    }
}
  1. ThreadPool::QueueJob

将新作业添加到池中;使用锁以避免数据竞争。

void ThreadPool::QueueJob(const std::function<void()>& job) {
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        jobs.push(job);
    }
    mutex_condition.notify_one();
}

使用方法:

thread_pool->QueueJob([] { /* ... */ });
  1. ThreadPool::busy
bool ThreadPool::busy() {
    bool poolbusy;
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        poolbusy = !jobs.empty();
    }
    return poolbusy;
}

busy() 函数可以在 while 循环中使用,这样主线程可以在调用线程池析构函数之前等待线程池完成所有任务。

  1. ThreadPool::Stop

停止水池。

void ThreadPool::Stop() {
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        should_terminate = true;
    }
    mutex_condition.notify_all();
    for (std::thread& active_thread : threads) {
        active_thread.join();
    }
    threads.clear();
}

一旦集成了这些成分,您就拥有了自己的动态线程池。这些线程总是运行,等待 工作要做。

如果有一些语法错误,我深表歉意,我输入了这段代码,但我的记忆力很差。抱歉我无法提供 您完整的线程池代码;这会违反我的职业操守。

Notes:

  • 使用匿名代码块,以便当它们退出时,std::unique_lock在其中创建的变量 超出范围,解锁互斥锁。
  • ThreadPool::Stop不会终止任何当前正在运行的作业,它只是等待它们完成active_thread.join().
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11 中的线程池 的相关文章

  • 格式说明符%02x

    我有一个简单的程序 include
  • 使用 ADAL v3 使用 ClientID 对 Dynamics 365 进行身份验证

    我正在尝试对我们的在线 Dynamics CRM 进行身份验证以使用可用的 API 我能找到的唯一关于执行此操作的官方文档是 https learn microsoft com en us dynamics365 customer enga
  • C#.Net 邮件将进入垃圾邮件文件夹

    我正在从 ASP net Web 应用程序发送电子邮件 邮件发送成功 没有失败 但大多数都进入了垃圾邮件文件夹 请帮助我克服垃圾邮件过滤器 我的发送邮件代码 public void SendMail string FromAddress s
  • 如何使用 openSSL 函数验证 PEM 证书的密钥长度

    如何验证以这种方式生成的 PEM 证书的密钥长度 openssl genrsa des3 out server key 1024 openssl req new key server key out server csr cp server
  • 2个对象,完全相同(除了命名空间)c#

    我正在使用第三方的一组网络服务 但遇到了一个小障碍 在我手动创建将每个属性从源复制到目标的方法之前 我想我应该在这里寻求更好的解决方案 我有 2 个对象 一个是 Customer CustomerParty 类型 另一个是 Appointm
  • 如何修复错误:“检测到无法访问的代码”

    我有以下代码 private string GetAnswer private int CountLeapYears DateTime startDate return count String answer GetAnswer Respo
  • 防止控制台应用程序中的内存工作集最小化?

    我想防止控制台应用程序中的内存工作集最小化 在Windows应用程序中 我可以这样做覆盖 SC MINIMIZE 消息 http support microsoft com kb 293215 en us fr 1 但是 如何在控制台应用程
  • 混合模型优先和代码优先

    我们使用模型优先方法创建了一个 Web 应用程序 一名新开发人员进入该项目 并使用代码优先方法 使用数据库文件 创建了一个新的自定义模型 这 这是代码第一个数据库上下文 namespace WVITDB DAL public class D
  • 用于在标头更改时重新编译的简单 C 项目的示例 makefile

    有谁有完整的 makefile 可以执行以下操作 如果 HEADER 文件发生更改 则重建项目 cpp 文件在 makefile 中列出 头文件未在 makefile 中列出 头文件允许与 cpp 文件具有不同的名称 部分cpp文件没有头文
  • 来自嵌入图像的 BitmapSource

    我的目标是在 WPF 窗口上重写 OnRender 方法中绘制图像 someImage png 它是嵌入资源 protected override void OnRender System Windows Media DrawingCont
  • 测量进程消耗的 CPU 时钟

    我用 C 语言编写了一个程序 它是作为研究结果创建的程序 我想计算程序消耗的确切 CPU 周期 精确的循环次数 知道我怎样才能找到它吗 The valgrind tool cachegrind valgrind tool cachegrin
  • 什么是竞争条件?

    编写多线程应用程序时 最常见的问题之一是竞争条件 我向社区提出的问题是 竞赛条件是什么 你如何检测它们 你如何处理它们 最后 如何防止它们发生 当两个或多个线程可以访问共享数据并且它们试图同时更改它时 就会出现竞争条件 由于线程调度算法可以
  • 让网络摄像头在 OpenCV 中工作

    我正在尝试让我的网络摄像头在 Windows 7 64 位中的 OpenCV 版本 2 2 中捕获视频 但是 我遇到了一些困难 OpenCV 附带的示例二进制文件都无法检测到我的网络摄像头 最近我发现这篇文章表明答案在于重新编译一个文件 o
  • 对于 C# Express 用户来说,有哪些好的工具可以识别可能重复的代码? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 也可以看看 有什么工具可以检查重复的 VB NET 代码吗 https stackoverflow c
  • 当Model和ViewModel一模一样的时候怎么办?

    我想知道什么是最佳实践 我被告知要始终创建 ViewModel 并且永远不要使用核心模型类将数据传递到视图 这就说得通了 让我把事情分开 但什么是Model 和ViewModel一模一样 我应该重新创建另一个类还是只是使用它 我觉得我应该重
  • 读取依赖步行者输出

    I am having some problems using one of the Dlls in my application and I ran dependency walker on it i am not sure how to
  • 调用 .ToArray() 时出现 ArgumentException

    我有一个经常被清除的列表 代码完全是这样的 VisitorAgent toPersist List
  • 每个客户端一个线程与线程服务器的排队线程模型之间的相对优点?

    假设我们正在构建一个线程服务器 旨在在具有四个核心的系统上运行 我能想到的两种线程管理方案是每个客户端连接一个线程和一个排队系统 正如第一个系统的名称所暗示的那样 我们将为每个连接到服务器的客户端生成一个线程 假设一个线程始终专用于程序的主
  • 构建 C# MVC 5 站点时项目之间的处理器架构不匹配

    我收到的错误如下 2017 年 4 月 20 日构建 13 23 38 C Windows Microsoft NET Framework v4 0 30319 Microsoft Common targets 1605 5 警告 MSB3
  • Streamwriter 覆盖 txt 文件中的文本

    有没有什么方法可以重新打开流写入器而不创建新的写入对象 因为此时 当调用 WriteOdd 时 streamwriter 正在覆盖在它之前调用的 WriteEven public void WriteEven StreamWriter wr

随机推荐

  • 如何在 OMNeT++ 仿真过程中更改网络配置?

    我想修改element的一些参数 iniOMNeT 中的文件 例如模拟运行期间节点的传输速率 例如当节点收到一些控制消息时 我发现信息表明可以以某种方式循环配置 如下所示 一些变量 几个值 但是里面没有条件子句 ini文件 并且无法将来自
  • 反应本机滚动视图-scrollToEnd-在Android上

    我正在尝试调用一个将在 onFocus on 上触发的函数TextInput这将使scrollView一直向下滚动 使用scrollToEnd 所以这是我的班级组件 class MyCMP extends Component constru
  • python维护两个不同的随机实例

    我正在尝试进行一些分析 出于 原因 我希望程序中的每个对象都有自己的种子 但没有全局种子 我能完成这样的事情吗 a random seed seed1 b random seed seed1 for a in range 5 print a
  • 在 C++ 中使用 getline() 进行文件输入

    我正在尝试用 C 完成一个简单的初学者任务 我有一个包含该行的文本文件 约翰 史密斯 31 就是这样 我想使用 ifstream 变量读取此数据 但我想将名称 John Smith 读入一个字符串变量 然后将数字 31 读入一个单独的 in
  • HTML5 Canvas 改变图像颜色

    我正在使用 jquery 滑块通过着色将图像颜色从蓝色更改为红色 范围为 100 到 100 这意味着当滑块值为 0 时 图像应看起来正常 默认值 并根据滑块值从蓝色 100 到 100 变化 在我的本地 我可以将图像加载到画布中 由于某种
  • 如何在 Python 中将整个列表作为命令行参数传递?

    我试图将两个包含整数的列表作为参数传递给 python 代码 但sys argv i 获取字符串列表形式的参数 输入看起来像 python filename py 2 3 4 5 1 2 3 4 我发现了以下 hack 来转换列表 strA
  • python获取函数中参数的变量名[重复]

    这个问题在这里已经有答案了 我想做这样的事情 fib 1 foo arg print arg argName the name of the variable that was put in for arg foo fib 并得到这个返回
  • 带有 .gitignore 的白名单目录

    我想在一个 git 存储库中有两个目录 我选择的方法是在顶级目录中创建 git 存储库 然后使用 gitignore 将感兴趣的两个目录列入白名单 要求位于我尝试的 gitignore 文件的注释中 Blacklist everything
  • 如何在滚动时从 SliverAppBar 淡入/淡出小部件?

    当用户在屏幕上滚动时 我想从 SliverAppBar 中 淡入 和 淡出 小部件 这是我想做的事情的一个例子 这是我的代码 没有 褪色 https gist github com nesscx 721cd823350848e3d594ba
  • 如何获取QGraphicsItem坐标系中光标单击的位置?

    我有一个QGraphicsScene with QGraphicsItem添加到其中 假设我点击了地图图像 QGraphicsItem 其中绘制绿色圆圈 如何根据此获得点击位置QGraphicsItem并不是QGraphicsScene坐标
  • 在 ASP .NET Core Web API Controller 中注入 Serilog 的 ILogger 接口

    我能找到的有关在 ASP NET Core Web 应用程序中使用 Serilog 的所有示例都使用 MicrosoftILogger
  • 核心数据保存UIImage

    我在这个数据库中有一个核心数据 我应该保存图像 那么如何保存只需要 URL 的图像 请举例 大图像 gt 100 kb 不应保存在 CoreData 中 因为它确实会增加托管对象的内存占用 对于这些图像 我会将 CoreData 中的路径保
  • 是否可以将对象解构为现有变量?

    我正在尝试使用对象解构来提取变量 但这些变量已经存在 如下所示 const x 1 y 2 Those should be 1 and 2 const x y complexPoint const point x y 有没有办法在不重命名解
  • 使用 WhatsApp Cloud API 发送 Commerce Manager 目录产品

    成功将我的目录从商务管理器添加到 Whatsapp 管理器后 现在我想通过 WhatsApp 云 API 向用户发送该产品 我看到了与许可 API 相关的链接 但没有找到运气 https developers facebook com do
  • 通过(弹出)菜单退出应用程序时窗口泄漏

    我希望你能帮助我 我有一个漏窗只要我通过 弹出 菜单选项退出我的应用程序在工具栏中 如果我通过正常方法退出应用程序 一切都很好 有人可以帮忙吗 我似乎找不到错误 我正在尝试找到正确的解决方案 我声明了 2 个静态字符串变量 但我猜这不是问题
  • 如何在 PostgreSQL ORDER BY 子句中使用 ALIAS?

    我有以下查询 SELECT title stock one stock two AS global stock FROM product ORDER BY global stock 0 title 在 PostgreSQL 8 1 23 中
  • 根据字符串匹配过滤字符串向量

    我有以下向量 X lt c mama log papa log mimo png mentor log 如何检索另一个仅包含以 m 开头并以 log 结尾的元素的向量 您可以使用grepl用正则表达式 X grepl m log X
  • 将 AudioBufferList 转换为 CMSampleBuffer 会产生意外结果

    我正在尝试转换AudioBufferList我从音频单元得到的CMSampleBuffer我可以传递到AVAssetWriter保存麦克风中的音频 这种转换有效 因为我为执行转换而进行的调用不会失败 但记录最终会失败 并且我在日志中看到一些
  • 为什么我的 MVC 应用程序中有两个 web.config 文件

    Views 文件夹中有一个 应用程序的根目录中还有另一个 我想注册一个自定义处理程序 但我不明白代码应该放在哪里 我在集成模式下运行 IIS7 所以我必须添加
  • C++11 中的线程池

    相关问题 关于 C 11 C 11 std 线程池 https stackoverflow com questions 12993451 c11 stdthread pooled C 11 中的 async launch async 是否会