【绝对有用】c++线程池相关技术点二

这行代码是C++多线程编程中的一种常见用法,具体地,它使用std::thread创建一个新的线程,并将该线程加入到一个std::vectorstd::thread容器中。下面是对这行代码的详细解释:

  1. threads:这是一个std::vectorstd::thread类型的容器,用于存储所有创建的线程。
  2. emplace_back:这是std::vector类的一个成员函数,用于在容器的末尾添加一个新的元素。与push_back不同,emplace_back直接在容器的存储位置上构造元素,避免了不必要的拷贝或移动操作,效率更高。
  3. std::thread:这是C++标准库提供的线程类,用于创建和管理线程。
  4. ThreadPool::threadFunction:这是一个指向成员函数的指针,表示要在线程中执行的函数。假设这个函数属于ThreadPool类。
  5. this:这是一个指向当前对象的指针,表示将当前ThreadPool对象的实例传递给threadFunction成员函数,以便该函数在执行时能够访问当前对象的成员变量和成员函数。
    综合起来,这行代码的意思是:创建一个新线程,该线程执行ThreadPool类的threadFunction成员函数,并将当前对象的指针作为参数传递给该函数。然后,将新创建的线程加入到threads向量中进行管理。

下面是一个简化的示例,演示了如何使用这行代码:

#include
#include
#include

class ThreadPool {
public:
ThreadPool() {
// 创建多个线程,每个线程执行threadFunction成员函数
for (int i = 0; i < 4; ++i) {
threads.emplace_back(&ThreadPool::threadFunction, this);
}
}

~ThreadPool() {// 等待所有线程完成for (auto& thread : threads) {if (thread.joinable()) {thread.join();}}
}void threadFunction() {std::cout << "Thread ID: " << std::this_thread::get_id() << std::endl;
}

private:
std::vectorstd::thread threads;
};

int main() {
ThreadPool pool;
return 0;
}
在这个示例中,ThreadPool类的构造函数创建了四个线程,每个线程执行threadFunction函数,并输出其线程ID。程序运行时,会创建四个线程,并输出相应的线程ID。


这行代码是C++多线程编程中条件变量(std::condition_variable)的一个常见用法。它用于线程同步,确保线程在满足特定条件之前处于等待状态。下面是对这行代码的详细解释:

  1. condition.wait(lock, predicate)
    • condition 是一个 std::condition_variable 对象,用于线程间的等待和通知机制。
    • wait 是 std::condition_variable 类的一个成员函数,使当前线程等待,直到收到通知或满足给定的条件。
    • lock 是一个 std::unique_lockstd::mutex 对象,用于管理互斥锁的所有权。
    • predicate 是一个 lambda 表达式或函数对象,用于判断条件是否满足。
  2. lock
    • 这是一个 std::unique_lockstd::mutex 对象,用于在等待期间自动管理互斥锁的上锁和解锁。
    • 在 wait 调用之前,lock 应该已经上锁。在 wait 期间,互斥锁会被解锁,以允许其他线程访问共享资源。
    • 当 wait 返回时,互斥锁会重新上锁,以保护共享资源。
  3. this { return !taskQueue.empty() || terminate; }
    • 这是一个 lambda 表达式,作为 wait 函数的谓词(predicate)。
    • 它捕获了当前对象的 this 指针,允许访问类的成员变量。
    • return !taskQueue.empty() || terminate; 是谓词的逻辑,当 taskQueue 非空或 terminate 为 true 时,返回 true,否则返回 false。
    综合起来,这行代码的意思是:当前线程等待,直到 taskQueue 非空或 terminate 为 true。在等待期间,互斥锁被解锁,以允许其他线程操作 taskQueue。当 taskQueue 非空或 terminate 为 true 时,线程会继续执行,并且互斥锁会重新上锁。

这是一个典型的生产者-消费者模型的实现,其中 taskQueue 是任务队列,terminate 是一个标志,指示线程是否应该终止。

下面是一个简化的示例,演示了如何使用这行代码:

#include
#include
#include
#include
#include <condition_variable>
#include

class ThreadPool {
public:
ThreadPool(size_t numThreads) : terminate(false) {
for (size_t i = 0; i < numThreads; ++i) {
threads.emplace_back(&ThreadPool::worker, this);
}
}

~ThreadPool() {{std::unique_lock<std::mutex> lock(mutex);terminate = true;}condition.notify_all();for (std::thread& thread : threads) {if (thread.joinable()) {thread.join();}}
}void enqueueTask(std::function<void()> task) {{std::unique_lock<std::mutex> lock(mutex);taskQueue.push(task);}condition.notify_one();
}

private:
void worker() {
while (true) {
std::function<void()> task;
{
std::unique_lockstd::mutex lock(mutex);
condition.wait(lock, this { return !taskQueue.empty() || terminate; });
if (terminate && taskQueue.empty()) {
return;
}
task = taskQueue.front();
taskQueue.pop();
}
task();
}
}

std::vector<std::thread> threads;
std::queue<std::function<void()>> taskQueue;
std::mutex mutex;
std::condition_variable condition;
bool terminate;

};

int main() {
ThreadPool pool(4);

pool.enqueueTask([] { std::cout << "Task 1 executed\n"; });
pool.enqueueTask([] { std::cout << "Task 2 executed\n"; });
pool.enqueueTask([] { std::cout << "Task 3 executed\n"; });
pool.enqueueTask([] { std::cout << "Task 4 executed\n"; });std::this_thread::sleep_for(std::chrono::seconds(2));return 0;

}
在这个示例中,ThreadPool 类创建了一个包含四个线程的线程池。每个线程在等待 taskQueue 中有任务时会处于等待状态。当有新任务加入队列时,线程会被唤醒并执行任务。程序在主线程中添加了四个任务,并让线程池处理这些任务。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/855241.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#心跳机制客户端

窗体&#xff08;richTextBox右显示聊天&#xff09; 步骤 点击链接按钮 tcpclient客户端步骤 1创建客户端对象 2连接服务器connect 3创建网络基础流发消息 .write发消息 4 创建网络基础流接消息 .read接消息 5 断开连接…

062、Python 解决命名冲突的两种方式

如下&#xff0c;在一个包里的两个模块分别定义了一个名称一样的函数&#xff1a; 包结构与模块内容&#xff1a; my_package/__init__.pymodule1.pymodule2.py模块一代码&#xff1a;module1.py def say_Hello():print("Hi!")模块二代码&#xff1a;module2.py …

python库离线安装方法(pyqt5离线安装方法)

在某些情况下&#xff0c;我们的计算机是无法联网的。 网上大部分方法&#xff1a; 这些方法都有个问题&#xff0c;就是库是需要依赖其它库的&#xff0c;你不知道它需要依赖什么库&#xff0c;就是提供了依赖库的列表也麻烦&#xff0c;依赖库也是有对应版本要求的&#xf…

自制调色小工具给图片加滤镜,修改图片红、绿、蓝通道及亮度,修改图片颜色

上篇&#xff1a; 上篇我们给地图添加了锐化、模糊等滤镜&#xff0c;这篇来写一个小工具给图片调色。 调色比锐化等滤镜要简单许多&#xff0c;直接拿到像素值修改即可。不需要用到卷积核。。。(*^▽^*) 核心原理就是图像结构&#xff0c;使用context.getImageData获取图像像…

JavaScript练手小技巧:JS 随机数小技巧

JS 里利用 Math.random() 可以产生0-1 之间的随机小数。如&#xff1a; let num1 Math.random(); // 0-1之间的随机数console.log(num1);// 0.05563019650398182 可以用随机数做一些有趣的事情。 一、指定范围的随机整数 // 随机整数function randomInt(min, max) {return …

cad怎么转成pdf文件?方法很简单!

cad怎么转成pdf文件&#xff1f;在数字化时代&#xff0c;CAD图纸的转换与共享已成为日常工作中的常态。无论是建筑设计师、工程师还是学生&#xff0c;都可能遇到需要将CAD文件转换为PDF格式的需求。本文将为您推荐三款高效的CAD转PDF软件&#xff0c;让您轻松实现文件格式的转…

【代码随想录算法训练Day35】LeetCode 1005. K 次取反后最大化的数组和、LeetCode 134.加油站、LeetCode 135.分发糖果

Day35 贪心第三天 LeetCode 1005. K 次取反后最大化的数组和 两步贪心&#xff0c;解决问题&#xff1a; 1.优先取反绝对值最大的负数 2.如果所有的数都非负了&#xff0c;就用绝对值最小的整数消耗掉剩余的k。 class Solution { public:static bool cmp(int a,int b){retur…

C++ 48 之 继承的基本语法

#include <iostream> #include <string> using namespace std;// 定义一个基类&#xff0c;把公共的部分写在这里&#xff0c;以后让别的类继承即可 class BasePage{ public:void header(){cout << "公共的头部"<< endl;}void footer(){cout…

STM32单片机-BKP和RTC

STM32单片机-BKP和RTC 一、Unix时间戳1.1 时间戳转换 二、BKP(备份寄存器)三、RTC(实时时钟)3.1 RTC工作原理 四、代码部分4.1 BKP备份寄存器4.2 RTC实时时钟 一、Unix时间戳 Unix时间戳定义为从伦敦时间的1970年1月1日0时0分0秒开始所经过的秒数&#xff0c;不考虑闰秒时间戳…

vue3使用echarts简单教程~~概念篇

没写过 写着玩玩 不足的地方还望小伙伴补充~~ 概念篇 文档奉上&#xff1a;数据集 - 概念篇 - 使用手册 - Apache EChartshttps://echarts.apache.org/handbook/zh/concepts/dataset <template><div id"main" style"width: 600px; height: 400px&…

集合进阶:增强for循环和lambda表达式

一.增强for遍历 1.增强for的底层是迭代器,为了简化迭代器的代码书写的。 2.他是JDK5之后出现的,其内部原理就是一个lterrator迭代器。 3.所有的单列集合和数组才能用增强for进行遍历 二.格式 for(元素的数据类型 变量名;数组或者集合){} 三.代码 Collection<String>…

72-UDP协议工作原理及实战

#ifndef UDPCOMM_H #define UDPCOMM_H#include <QMainWindow> #include <QUdpSocket> // 用于发送和接收UDP数据报 #include <QtNetwork>QT_BEGIN_NAMESPACE namespace Ui { class udpComm; } QT_END_NAMESPACEclass udpComm : public QMainWindow {Q_OBJECT…

定个小目标之刷LeetCode热题(23)

今天写这道题&#xff0c;背过八股文的都应该知道LRU算法缓存的基本原理&#xff0c;在 Java 语言中&#xff0c;同样有类似的数据结构 LinkedHashMap&#xff0c;本题我们采用自己创建哈希表双链表的形式简单实现一下 对于get操作&#xff1a;通过cache.get(key)获取&#xff…

格雷母线定位与控制系统:确保机车平稳运行的关键

微深节能的格雷母线高精度位移检测系统是一种高精度的位置检测设备&#xff0c;它通过发射和接收信号来确定移动物体的实时位置。在机车定位系统中&#xff0c;格雷母线被安装在固定的轨道上&#xff0c;而机车上的检测装置则负责读取这些信号&#xff0c;从而准确计算出机车的…

一文弄懂 Python os.walk(),轻松搞定文件处理和目录遍历

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ Python os 模块的 walk() 方法以自顶向下或自底向上的方式遍历指定的目录树&#xff0c;从而显示目录树中的文件名。对于目录树中的每个目录&#xff0c;os.walk() 方法都会产生一个包含目录路径、当前…

Java17 --- redis7缓存双写一致性

一、缓存双写一致性 如果redis中有数据&#xff1a;需要和数据库中的值相同。如果redis中没有数据&#xff1a;数据库中的值要是最新值&#xff0c;且准备回写redis。只读缓存。读写缓存&#xff1a;①、同步直写策略&#xff1a;写数据库后也同步写redis缓存&#xff0c;缓存…

光纤三维布里渊温度和应变分布matlab模拟与仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 光纤三维布里渊温度和应变分布matlab模拟与仿真。其中 , 布里渊散射是光波与声波在光纤中传播时相互作用而产生的光散射过程 , 在不 同的条件下 , 布里渊散射又分…

70、最长上升子序列

最长上升子序列 题目描述 给定一个长度为N的数列&#xff0c;求数值严格单调递增的子序列的长度最长是多少。 输入格式 第一行包含整数N。 第二行包含N个整数&#xff0c;表示完整序列。 输出格式 输出一个整数&#xff0c;表示最大长度。 数据范围 1 ≤ N ≤ 1000 &am…

数据结构与算法-字符出现的次数

问题描述 以下是这个找出字符串中字符串出现频率最多的字符。大家可以自行研究一下&#xff0c;题目不难&#xff0c;我今天尝试使用C语言来完成解答&#xff0c;但是在解答过程居然出现了一个意想不到的问题。可能是高级语言用多了&#xff0c;C语言某些函数的限制和风险忘记管…

C++之std::type_identity

目录 1.简介 2.C20的std::type_identity 3.使用 type_identity 3.1.阻止参数推导 3.1.1.模板参数推导过程中的隐式类型转换 3.1.2.强制显式实例化 3.2.阻止推断指引 3.3.类型保持 3.4.满足一些稀奇古怪的语法 4.示例 5.总结 1.简介 std::type_identity 是 C17 引入的…