线程队列C ++

如何解决线程队列C ++

''''原始帖子已被编辑''

如何在C ++中为两个for循环创建线程池?对于0到6之间的每个数字,我需要运行start_thread函数22次。根据我使用的机器,我将有灵活的可用线程数。如何创建一个池以将空闲线程分配给下一个嵌套循环?

for (int t=0; t <22; t++){
    for(int p=0; p<6; p++){
        thread th1(start_thread,p);
        thread th2(start_thread,p);
        th1.join();
        th2.join();
     }
}

解决方法

不确定自己想要什么,但是也许是这样的。

for (int t=0; t <22; t++){
        std::vector<std::thread> th;
        for(int p=0; p<6; p++){
                th.emplace_back(std::thread(start_thread,p));
        }
        for(int p=0; p<6; p++){
                th[i].join();
        }
}

(或者可能置换两个循环)


编辑,如果要控制线程数

#include <iostream>
#include <thread>
#include <vector>

void
start_thread(int t,int p)
{
  std::cout << "th " << t << ' ' << p << '\n';
}

void
join_all(std::vector<std::thread> &th)
{
  for(auto &e: th)
  {
    e.join();
  }
  th.clear();
}

int
main()
{
  std::size_t max_threads=std::thread::hardware_concurrency();
  std::vector<std::thread> th;
  for(int t=0; t <22; ++t)
  {
    for(int p=0; p<6; ++p)
    {
      th.emplace_back(std::thread(start_thread,t,p));
      if(size(th)==max_threads)
      {
        join_all(th);
      }
    }
  } 
  join_all(th);
  return 0;
}
,

如果您不想依赖第三方库,这很简单。

只需创建多个您喜欢的线程,然后让它们从某个队列中选择一个“作业”即可。

例如:

#include <iostream>
#include <mutex>
#include <chrono>
#include <vector>
#include <thread>
#include <queue>

void work(int p)
{
  // do the "work"
  std::this_thread::sleep_for(std::chrono::milliseconds(200));
  std::cout << p << std::endl;
}

std::mutex m;
std::queue<int> jobs;
void worker()
{
  while (true)
  {
    int job(0);
    // sync access to the jobs queue
    {
      std::lock_guard<std::mutex> l(m);
      if (jobs.empty())
        return;
      job = jobs.front();
      jobs.pop();
    }
    work(job);
  }
}

int main()
{
  // queue all jobs
  for (int t = 0; t < 22; t++) {
    for (int p = 0; p < 6; p++) {
      jobs.push(p);
    }
  }

  // create reasonable number of threads
  static const int n = std::thread::hardware_concurrency();
  std::vector<std::thread> threads;
  for (int i = 0; i < n; ++i)
    threads.emplace_back(std::thread(worker));
  // wait for all of them to finish
  for (int i = 0; i < n; ++i)
    threads[i].join();
}

[添加]显然,您不希望在生产代码中使用全局变量。这只是一个演示解决方案。

,

停止尝试编写代码并绘制出您需要做的事情以及完成这些工作所需的部分。

您需要一个队列来保存作业,一个互斥体来保护该队列,这样线程就不会因同时访问而使它混乱,还有N个线程。

每个线程函数都是一个循环

  1. 抓住互斥锁,
  2. 从队列中获得工作,
  3. 释放互斥量,并且
  4. 处理工作。

在这种情况下,我将通过在步骤2中队列中没有更多作业时退出循环和线程来简化事情。在生产中,您将拥有线程块并在队列中等待,以便它仍然可用服务以后添加的工作。

使用允许您向队列中添加作业的函数,用于启动N个线程的函数以及可以在所有正在运行的线程上加入的函数,将其包装在类中。

main定义了该类的一个实例,提供了作业,启动了线程池,然后阻塞了联接,直到每个人都完成了。

一旦您将设计打造成具有很高信心的事情,您就会完成所需的工作,然后开始编写代码。在没有计划的情况下编写代码,尤其是多线程代码,并且您需要进行大量的调试和重写,通常会大大超出设计时间。

,

自C ++ 17起,您可以在标准库中的许多算法中使用execution policies之一。这可以大大简化处理多个工作包的过程。通常,幕后工作是从内置线程池中选择线程,并高效地将工作分配给它们。它通常在Linux和Windows中都使用 just足够™线程,并且将使用剩下的所有CPU(当CPU开始以最大频率旋转时,所有内核上的空闲率为0% )-很奇怪,而Linux和Windows都没有“呆滞”。

这里,我使用了执行策略std::execution::parallel_policy(由std::execution::par常量表示)。如果您可以准备需要完成的工作并将其放入std::vector之类的容器中,那将非常容易。

#include <algorithm>
#include <chrono>
#include <execution>  // std::execution::par
#include <iostream>
// #include <thread>  // not needed to run with execuion policies
#include <vector>

struct work_package {
    work_package() : payload(co) { ++co; }
    int payload;
    static int co;
};
int work_package::co = 10;

int main() {
    std::vector<work_package> wps(22*6);                         // 132 work packages
    for(const auto& wp : wps) std::cout << wp.payload << '\n';   // prints 10 to 141

    // work on the work packages
    std::for_each(std::execution::par,wps.begin(),wps.end(),[](auto& wp) {
        // Probably in a thread - As long as you do not write to the same work package
        // from different threads,you don't need synchronization here.

        // do some work with the work package
        ++wp.payload;
    });

    for(const auto& wp : wps) std::cout << wp.payload << '\n';   // prints 11 to 142
}

使用g++,您可能需要安装tbbThe Threading Building Blocks),并且还需要链接到:-ltbb

  • apt install libtbb-dev在Ubuntu上。
  • dnf install tbb-devel.x86_64在Fedora上。

其他发行版可能称之为不同。

Visual Studio(2017年及更高版本)会自动链接到适当的库(如果我现在误记了,也将链接到tbb。)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-