C++11 Thead线程和线程池
参考资料:
2、5.lock_guard 与 std::unique_lock-陈子青的编程学习课堂 (seestudy.cn)
3、C++11 多线程编程-小白零基础到手撕线程池_哔哩哔哩_bilibili
一、 C++11 Thead线程库的基本使用
# include <thread>
std::thread t(function_name, args...); // 线程开始运行
t.join() // 等待线程完成
t.detach() // 分离线程,让它在后台运行
示例代码一
#include <iostream>
#include <thread>
void print_message() { std::cout << "Hello, world!" << std::endl;
}
int main() { std::thread t(print_message);t.join(); return 0;
}
示例代码二
#include <iostream>
#include <thread>
#include <functional> // 包含 std::ref
using namespace std;void increment(int& x) {x++; // 对参数进行递增操作
}int main() {int num = 5;thread t(std::ref(increment), std::ref(num)); // 可用方式一// thread t(increment, std::ref(num)); // 可用方式二// thread t(increment, num); 这个会报错!!!t.join();cout << "After increment: " << num << endl;cout << "increment: " << increment << endl;return 0;
}
二、 C++11 Thead易错
易错一:多线程使用了局部变量
1、有些运行环境下会出现Aborted (core dumped),原因是a是局部变量,在test作用域内会消失,而在线程内继续引用了a;
2、有些运行环境是不会报错,但是会出现结果不可预测
hq@nuc:~/java/my-project2$ ./a.out
32766
示例代码
#include <iostream>
#include <thread>
std::thread t;
// int a = 1; // 正确示例应该将a变成全局区域
void foo(int& x) {std::this_thread::sleep_for(std::chrono::seconds(2));x += 1;std::cout << x << std::endl;
}void test(){int a = 1;t = std::thread(foo, std::ref(a));
}int main() {test();t.join();return 0;
}return 0;
}
易错二:多线程使用了局部变量
1、有些运行环境下会出现Aborted (core dumped),原因是a是局部变量,在test作用域内会消失,而在线程内继续引用了a;
2、有些运行环境是不会报错,但是会出现结果不可预测
(py37) hq@nuc:~/java/my-project2$ ./a.out
0
1
示例代码二:
#include <iostream>
#include <thread>
std::thread t;
void foo(int* x) {std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << *x << std::endl;*x += 1;std::cout << *x << std::endl;
}int main() {int *a = new int(20);t = std::thread(foo, a);delete a;t.join();return 0;
}
正确示例
#include <iostream>
#include <thread>
// std::thread t;
void foo(int* x) {std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << *x << std::endl;*x += 1;std::cout << *x << std::endl;
}int main() {std::shared_ptr<int> sharedPtr = std::make_shared<int>(42);std::thread t([sharedPtr]() {foo(sharedPtr.get());});std::thread t(foo, sharedPtr.get());t.join();return 0;
}
线程池
#include <iostream> // 包含标准输入输出流的头文件。
#include <thread> // 包含线程相关的头文件。
#include <vector> // 包含向量容器的头文件。
#include <queue> // 包含队列容器的头文件。
#include <mutex> // 包含互斥量的头文件,用于实现线程安全。
#include <condition_variable> // 包含条件变量的头文件,用于实现线程同步。
#include <functional> // 包含函数对象的头文件,用于传递任务函数。
#include <glog/logging.h>class ThreadPool { // 定义了一个名为 ThreadPool 的类。
public:ThreadPool(size_t numThreads) : stop(false) { // 线程池的构造函数,接受一个参数 numThreads,表示线程池中的线程数量。初始化列表 stop(false) 初始化了成员变量 stop,将其设置为 false,表示线程池初始状态下不处于停止状态。for (size_t i = 0; i < numThreads; ++i) { // 使用循环创建指定数量的工作线程。workers.emplace_back( // 在工作线程向量中添加一个新的线程,使用 Lambda 表达式初始化线程的执行函数。[this] {while (true) { // 工作线程的主循环,保持线程池始终处于运行状态。std::function<void()> task; // 定义了一个函数对象 task,用于存储要执行的任务。{std::unique_lock<std::mutex> lock(queueMutex); // 创建一个互斥锁 lock,用于保护任务队列。condition.wait(lock, [this] { return stop || !tasks.empty(); }); // 等待条件变量,直到满足 stop 或者任务队列不为空的条件。if (stop && tasks.empty()) { return; } // 如果线程池被要求停止并且任务队列为空,则退出线程。task = std::move(tasks.front()); // 从任务队列中获取任务并移动到 task 中。tasks.pop(); // 从任务队列中移除任务。}task(); // 执行任务。}});}}template<class F>void enqueue(F&& f) { // 定义一个模板函数 enqueue,用于向任务队列中添加任务。{std::unique_lock<std::mutex> lock(queueMutex); // 创建一个互斥锁 lock,用于保护任务队列。tasks.emplace(std::forward<F>(f)); // 将任务添加到任务队列中。}condition.notify_one(); // 通知一个等待中的线程有新任务可执行。}~ThreadPool() { // 线程池的析构函数,用于停止线程池并等待所有线程完成工作。{std::unique_lock<std::mutex> lock(queueMutex); // 创建一个互斥锁 lock,用于保护任务队列。stop = true; // 将停止标志设置为 true,表示线程池将要停止。}condition.notify_all(); // 通知所有等待中的线程停止。for (std::thread& worker : workers) { worker.join(); } // 等待所有工作线程完成工作并退出。}private:std::vector<std::thread> workers; // 存储工作线程的向量。std::queue<std::function<void()>> tasks; // 存储任务的队列,每个任务都是一个可调用的函数对象。std::mutex queueMutex; // 保护任务队列的互斥量。std::condition_variable condition; // 用于线程同步的条件变量。bool stop; // 表示线程池是否停止的标志。
};// 示例任务函数
void taskFunction(int taskId) {// std::cout << "Task " << taskId << " is running in thread " << std::this_thread::get_id() << std::endl;// std::cout << "Task " << taskId << std::endl;LOG(INFO) << "Task " << taskId << " is running in thread " << std::this_thread::get_id() << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));
}int main() {ThreadPool pool(10); // 创建一个拥有4个线程的线程池// 将一些任务提交到线程池for (int i = 0; i < 1000; ++i) {pool.enqueue([i] { taskFunction(i); });}// 主线程等待所有任务完成std::this_thread::sleep_for(std::chrono::seconds(2)); // 等待足够的时间以确保所有任务完成return 0;
}
线程数组、任务数组
1、线程数组,是不能关闭的,只能是while(true)
2、线程数组,循环从任务数组中取任务
相关文章:
C++11 Thead线程和线程池
参考资料: 2、5.lock_guard 与 std::unique_lock-陈子青的编程学习课堂 (seestudy.cn) 3、C11 多线程编程-小白零基础到手撕线程池_哔哩哔哩_bilibili 一、 C11 Thead线程库的基本使用 # include <thread> std::thread t(function_name, args...); // 线…...

Windows版Apache 2.4.59解压直用(免安装-绿色-项目打包直接使用)
windows下Apache分类 Apache分为 安装版和解压版 安装版: 安装方便,下一步------下一步就OK了,但重装系统更换环境又要重新来一遍,会特别麻烦 解压版(推荐): 这种方式(项目打包特别方便&#x…...

刀具表面上的微结构
刀具表面微结构通常指在刀具表面对特定功能设计的微观纹理,这些纹理可以是沟槽、凹坑、凸起或任何其他形式的微观图案。这些微结构的设计和应用是为了改善刀具的切削性能,减少切削力和切削温度,提高切削效率和精度,同时降低切削液…...

css3实现微信扫码登陆动画
在做微信扫码登陆时,出现一个背景光图上下扫码动画,用css3图片实现。 实现原理: 1.准备一个渐变的背景.png图 2.css动画帧实现动画 看效果: css代码: #wx-scan{position: absolute;top:0px;left: 50%;z-index: 3;ma…...
vue3 导入excel数据
所需包 "xlsx": "^0.18.5"页面导入包 import * as XLSX from xlsx; import {genFileId, UploadProps, UploadRawFile,ElTable } from element-plus;页面 <el-upload accept".xlsx" :on-change"changeExcel" :on-exceed"ha…...
C# linq 根据多字段动态Group by
实现类: public static class LinqHepler {/// <summary>/// 根据单个字段动态Group/// </summary>/// <typeparam name"T"></typeparam>/// <param name"source"></param>/// <param name"prop…...

C语言学习/复习22----阶段测评编程题
一、阶段测评练习 题1: 题2:...

LeetCode-1766. 互质树【树 深度优先搜索 广度优先搜索 数组 数学 数论】
LeetCode-1766. 互质树【树 深度优先搜索 广度优先搜索 数组 数学 数论】 题目描述:解题思路一:DFS 中记录节点值的深度和编号,回溯写法。关键点是1 < nums[i] < 50解题思路二:0解题思路三:0 题目描述࿱…...
“数据安全服务能力”评定资格认证!不容错过
数据安全服务能力评定是指对数据安全服务提供商从事数据安全服务综合能力的评定,包括技术能力、服务能力、质量保证能力、人员构成与素质、经营业绩、资产状况等要素。 一、能力评定类型与等级 数据安全服务能力分为二个类型:数据安全评估、数据安全建…...
【MATLAB 分类算法教程】_3麻雀搜索算法优化支持向量机SVM分类 - 教程和对应MATLAB代码
分类代码案例3:麻雀搜索算法优化支持向量机SVM分类 - MATLAB完全代码教程 1. 初始化代码2.读取数据代码3.数据预处理代码4.利用麻雀搜索算法SSA求解最佳的SVM参数c和g代码5.根据最佳的参数进行SVM模型训练代码6.SVM模型预测代码7.准确率分析以及分类结果对比作图代码本文以红酒…...
利用机器学习库做动态定价策略的例子
动态定价是一个复杂的问题,涉及到市场需求、库存、竞争对手行为、季节性因素等多个变量。在实际应用中,动态定价通常需要复杂的模型和大量的数据分析。我选择使用Python(Golearn库)进行机器学习模型的训练和部署,而将G…...

Tcpdump -r 解析pcap文件
当我们使用命令抓包后,想在命令行直接读取筛选怎么办?-r参数就支持了这个 当你使用 tcpdump 的 -r 选项读取一个之前捕获的数据包文件,并想要筛选指定 IP 地址和端口的包时,你可以在命令中直接加入过滤表达式。这些过滤表达式可以…...

[dvwa] sql injection(Blind)
blind 0x01 low 1’ and length(version()) 6 # syntax: substr(string , from<start from 1>, cut length) 1’ and substr(version(),1,1) ‘5’ # 1’ and substr(version(),2,1) ‘.’ # 1’ and substr(version(),3,1) ‘7’ # 1’ and substr(version(),4,…...

linux 挂载云盘 NT只能挂载2T,使用parted挂载超过2T云盘
一、删除原来挂载好的云盘和分区 1、查看挂载号的云盘 fdisk -l 发现我们有5千多G但是只挂载了2T,心里非常的慌张!十分的不爽! 好,我们把它干掉,重新分区! 2、解除挂载 umount /homeE 没保存跳转到&…...

用Skimage学习数字图像处理(021):图像特征提取之线检测(下)
本节是特征提取之线检测的下篇,讨论基于Hough变换的线检测方法。首先简要介绍Hough变换的基本原理,然后重点介绍Skimage中含有的基于Hough变换的直线和圆形检测到实现。 目录 10.4 Hough变换 10.4.1 原理 10.4.2 实现 10.4 Hough变换 Hough变换&…...
ArduPilot飞控之Gazebo + SITL + MP的Jetson Orin环境搭建
ArduPilot飞控之Gazebo SITL MP的Jetson Orin环境搭建 1. 源由2. Linux环境整理3. 安装Gazebo环境3.1 安装Gazebo3.2 安装插件3.3 配置插件3.4 测试Gazebo 4. 安装Arudpilot-SITL环境4.1 克隆工程4.2 编译准备4.3 环境配置4.4 配置编译4.5 测试运行 5. 测试运行6. 参考资料 1…...
前端错误监控的方法有哪些
前端错误监控是指通过各种手段收集、分析和处理前端应用运行中发生的错误 常用的前端错误监控的方法有 使用 try catch 方法 捕获特定代码块中的错误多用于处理特定函数或代码段可能抛出的异常,尤其是异步代码网络请求错误监控 promise.catchtry catch全局错误处理…...

✌粤嵌—2024/3/11—跳跃游戏
代码实现: 方法一:递归记忆化 int path; int used[10000];bool dfs(int *nums, int numsSize) {if (path numsSize - 1) {return true;}for (int i 1; i < nums[path]; i) {if (used[path i]) {continue;}path i;used[path] 1;if (dfs(nums, num…...

Docker入门实战教程
文章目录 Docker引擎的安装Docker比vm虚拟机快 Docker常用命令帮助启动类命令镜像命令docker imagesdocker searchdocker pulldocker system dfdocker rmi 容器命令redis前台交互式启动redis后台守护式启动Nginx容器运行ubuntu交互式运行tomcat交互式运行对外暴露访问端口 Dock…...

数据结构初阶:二叉树(一)
树概念及结构 树的概念 树是一种 非线性 的数据结构,它是由 n ( n>0 )个有限结点组成一个具有层次关系的集合。 把它叫做树是因 为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的 。 有一个特殊的结点&a…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能
指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
数据库——redis
一、Redis 介绍 1. 概述 Redis(Remote Dictionary Server)是一个开源的、高性能的内存键值数据库系统,具有以下核心特点: 内存存储架构:数据主要存储在内存中,提供微秒级的读写响应 多数据结构支持&…...