C++11 线程池:轻量级高并发解决方案

C++11 线程池:轻量级高并发解决方案

线程池(Thread Pool)是一种线程管理的机制,它包含了多个预先创建的线程,用于执行多个任务,这些任务被放入任务队列中等待执行。

满足我们的生产者和消费者模型。
在这里插入图片描述

线程池的核心组成部分。
  • 任务队列 -----按顺序等待要处理的任务。
  • 线程数组----- 多个已启动的线程,从任务队列拿取任务处理。
  • 互斥锁。
  • 条件变量。
  • 任务。
线程池的好处:
  • 减少线程的创建和销毁次数,提高系统的性能和效率。因为我们每次创建和销毁线程都是有开销的。
  • 活动的线程需要消耗系统资源,如果启动太多,会导致系统由于过度消耗内存或切换过度而导致系统资源不足。
  • 通过重复利用已创建的线程 ,避免了频繁创建和销毁线程的性能开销。

基于C++11实现的线程池:感受C++11的魅力

当然实际项目中的线程池可能会更复杂。但是对于初学者 ,你能够了解到这里已经足够了。

ThreadPool.h 线程池必要的接口 ,和属性。
#ifndef _THREAD_POOL_H_
#define _THREAD_POOL_H_#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <queue>
#include <functional>class ThreadPool {
public:// 创建线程池单例static ThreadPool* getIntance(int num) {static ThreadPool* threadPool = nullptr;// call_once()   ,保证函数只能执行一次 ,只能在多线程里面使用std::call_once(flag_, init_threadPool, threadPool, num);return threadPool;}// 往线程池中添任务template <typename F , typename...  Agrs>void push_task(F &&f , Agrs&&...  agrs);private:static void init_threadPool(ThreadPool*& p, int num) {p = new ThreadPool(num);}ThreadPool(int num = 4);   // 默认线程数是 4 ~ThreadPool();std::queue<std::function<void()>>task_queue_;   // 任务队列std::vector<std::thread>threads;              // 线程数组std::mutex mutex_;   // 互斥锁std::condition_variable c_variable_;  // 条件变量bool isStop_;        // 线程池是否终止static std::once_flag flag_;    // call_once()  需要的flag
};// 往任务队列添加任务
template <typename F, typename...  Agrs>
void ThreadPool::push_task(F&& f, Agrs&&...  agrs) {// 将函数和参数进行绑定// forward 实现完美转换std::function<void()>task = std::bind(std::forward<F>(f), std::forward<Agrs>(agrs)...);{std::unique_lock<std::mutex>lock(mutex_);// 加入任务队列task_queue_.emplace(task);}c_variable_.notify_one();   // 唤醒一个线程来执行
}#endif // !_THREAD_POOL_H
ThreadPool.cpp 相关接口的具体实现。
#include "ThreadPool.h"std::once_flag ThreadPool::flag_;ThreadPool::ThreadPool(int num):isStop_ ( false ) {for (int i = 0; i < num ; i++) {threads.emplace_back([this]( ) {while ( true ) {std::unique_lock<std::mutex>lock(mutex_);c_variable_.wait(lock, [ = ]() {return (!task_queue_.empty() || isStop_);});if ( isStop_  && task_queue_.empty() ) {  // 如果被线程池终止了return;}std::cout << "线程池处理" << std::endl;// 从任务队列,拿出任务执行std::function<void( )>task(std::move(task_queue_.front()));task_queue_.pop();task();}});}
}ThreadPool::~ThreadPool( ) {{std::unique_lock<std::mutex>lock(mutex_);isStop_ = true;if (!task_queue_.empty())   c_variable_.notify_all();   // 唤醒所有线程去执行任务}for ( auto& a : threads ) {a.join();}
}
测试代码:
#include "ThreadPool.h"
#include <iostream>
#include <algorithm>
#include <chrono>void print(const char *name) {std::cout << "name :" << name << std::endl;
}int getMax(int a, int b) {return std::max(a, b);
}void sort(std::vector<int>*&value) {// 默认是升序std::sort(value->begin(), value->end());   // 
}int main() {// 创建一个线程池 ,线程数为4ThreadPool *pool = ThreadPool::getIntance( 4 );std::vector<int>value;//for (int i = 1; i < 10; i++) {//	pool->push_task( [i]() {//		std::cout << "task runing " << i << std::endl;//		std::this_thread::sleep_for(std::chrono::seconds(1)); // 休眠1秒//		std::cout << "task stop : " << i << std::endl;//		});//}for (int i = 10; i > 0; i--) {value.emplace_back(i);}// 将任务投入线程池,让线程来处理pool->push_task(print, "小美");   // 输出小美pool->push_task(sort, &value);   // 升序排序std::this_thread::sleep_for(std::chrono::seconds(10)); // 休眠10秒for (int i = 0; i < value.size(); i++) {std::cout << value[i] << std::endl;}std::cout << "\n";return 0;
}
测试结果:

在这里插入图片描述

效果达到预期 ,当然你也可以多写几个测试案例。

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

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

相关文章

一文带你快速了解GPT-4o!内含免费使用指南!

一、GPT-4o简介 北京时间5月14日&#xff0c;OpenAI举行春季发布会。OpenAI在活动中发布了新旗舰模型“GPT-4o”&#xff01;据OpenAI首席技术官穆里穆拉蒂&#xff08;Muri Murati&#xff09;介绍&#xff0c;GPT-4o在继承GPT-4强大智能的同时&#xff0c;进一步提升了文本、…

常用限流方式

1. 令牌桶算法&#xff08;Token Bucket&#xff09; 令牌桶算法是一种常用的限流算法&#xff0c;它通过维护一个固定容量的令牌桶&#xff0c;以限制单位时间内通过的请求数量。当请求到达时&#xff0c;会从令牌桶中获取一个令牌&#xff0c;如果令牌桶中没有令牌&#xff…

如何使用Python进行网页爬取

Python爬虫案例可以有很多种&#xff0c;但我会为你提供一个简单的案例&#xff0c;该案例使用Python的requests库来爬取一个网页的内容&#xff0c;并使用BeautifulSoup库来解析HTML并提取特定的信息。 假设我们要从某个新闻网站&#xff08;例如&#xff1a;示例网站&#x…

电力场景设备漏油检测数据集VOC+YOLO格式338张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;338 标注数量(xml文件个数)&#xff1a;338 标注数量(txt文件个数)&#xff1a;338 标注类别…

第N1周:one-hot编码

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子 1.什么是one-hot编码 One-Hot编码是一种常用于机器学习中的特征编码方式&#xff0c…

Qt---项目的创建及运行

一、创建第一个Qt程序 1. 点击创建项目后&#xff0c;选择项目路径以及给项目起名称 名称&#xff1a;不能有中文、不能有空格 路径&#xff1a;不能有中文路径 2. 默认创建有窗口类myWidget&#xff0c;基类有三种选择&#xff1a;QWidget、QMainWindow、QDialog 3. m…

Redis为什么快

用了那么久的redis&#xff0c;突然意识到这个问题答不上来&#xff0c;只知道内存数据库&#xff0c;内存的读写性能快于磁盘。 1. 内存存储 Redis 是一个基于内存的数据库&#xff0c;它将所有的数据都保存在内存中&#xff0c;这使得读取的速度非常快。内存读写速度远超于…

#自学习# 记一次py脚本打开浏览器页面

在项目总结中&#xff0c;遇到系统后台利用浏览器拉起一个已知路径页面的需求&#xff0c;趁着机会整理下。实现起来比较简单&#xff0c;浏览器默认谷歌。 一、技术原理 Selenium&#xff1a;Selenium 是一个用于自动化 Web 浏览器的工具&#xff0c;可模拟用户在浏览器中的各…

socket接口定义范围及操作

Socket接口&#xff0c;也称为套接字接口&#xff0c;是用于实现网络通信的一种编程接口。它定义了一系列的操作和函数&#xff0c;允许应用程序通过网络进行数据传输。 Socket接口不仅仅局限于特定的操作系统或网络协议&#xff0c;而是在多种网络环境中通用&#xff0c;包括但…

Python面试题【数据结构和算法部分101-130】

Python面试题【数据结构和算法部分101-130】 Python面试题【数据结构和算法部分101-130】 Python面试题【数据结构和算法部分101-130】 问题&#xff1a;如何在Python中实现二分查找&#xff1f; 答案&#xff1a; def binary_search(arr, target):low, high 0, len(arr) - 1…

奔向光明阿波罗(五)

下半场的艰难曙光 有“中国无人驾驶黄埔军校”之称的百度&#xff0c;最初的雄心是给未来的智能汽车安上一颗“百度之心”&#xff0c;取得类似于“Intel Inside“的品牌强强联合效果。阿波罗希望为汽车行业的玩家提供一个“开放、完整、安全”的开源平台&#xff0c;帮助他们结…

正则表达式中的$分组使用示例

正则表达式中的 $ 符号通常用于表示字符串的结束位置&#xff0c;但当你在替换操作或者某些特殊上下文中提到 $ 后跟数字&#xff08;如 $1, $2, etc.&#xff09;&#xff0c;这并不表示结束位置&#xff0c;而是引用之前正则表达式捕获组的内容。 以下是使用 $ 引用捕获组的…

计算机视觉与深度学习实战:以Python为工具,基于块匹配的全景图像拼接

注意:本文的下载教程,与以下文章的思路有相同点,也有不同点,最终目标只是让读者从多维度去熟练掌握本知识点。 下载教程:计算机视觉与深度学习实战-以MATLAB和Python为工具_基于块匹配的全景图像拼接_项目开发案例教程.pdf 计算机视觉作为人工智能领域的一个重要分支,旨在…

成都百洲文化传媒有限公司怎么样?靠谱吗?

在数字化浪潮席卷全球的今天&#xff0c;电商行业正以前所未有的速度蓬勃发展。作为这一变革的积极参与者和推动者&#xff0c;成都百洲文化传媒有限公司以其专业的电商服务&#xff0c;正逐渐成为行业内的佼佼者。 一、公司简介 成都百洲文化传媒有限公司自成立以来&#xff…

邦芒宝典:离职前一定要做的几件事帮你刷爆好感

​​这个问题&#xff0c;关键还是要看这位有本事的员工的职业素养如何。虽说工有本事的员工往往都会具备比较高的职业素养&#xff0c;比如强专业能力、强沟通、强执行、正确的价值观与职业操守等等&#xff0c;但也可能有些人能力是不错&#xff0c;但素养比较低&#xff0c;…

MyBatis的创建和测试

创建项目点击Spring Initializr然后点击next 点击SQL 选择里面的Mybatis Framework和Mysql Driver 按如下图片创建项目 user表中的数据 #下面这些内容是为了让MyBatis映射 #指定Mybatis的Mapper文件 mybatis.mapper-locationsclasspath:mappers/*xml #指定Mybatis的实体目录 my…

【Java】IDEA自动生成类图和时序图

【Java】IDEA自动生成类图和时序图 idea 的强大之处在于此&#xff0c;它包含了很多小插件&#xff0c;我们不需要再次下载相关插件&#xff0c;只需要在idea中小小的设置一下就可以了,下面是设置方法&#xff0c;我用的是idea2020版本 打开设置File -> Settings->Diagr…

Netty-面试题(中)(五十)

关于零拷贝和堆外内存 Java在将数据发送出去的时候&#xff0c;会先将数据从堆内存拷贝到堆外内存&#xff0c;然后才会将堆外内存再拷贝到内核态&#xff0c;进行消息的收发&#xff0c;代码如下: 所以&#xff0c;我们发现&#xff0c;假如我们在收发报文的时候使用直接内存&…

工业互联网网络安全如何保障

随着工业4.0时代的到来&#xff0c;工业互联网&#xff08;IIoT&#xff09;成为了推动制造业数字化转型的重要力量。然而&#xff0c;随着工业互联网的快速发展&#xff0c;其网络安全问题也日益凸显。保障工业互联网网络安全&#xff0c;不仅关系到企业的正常运营&#xff0c…

Gin框架返回Protobuf类型:提升性能的利器

在构建高效、高性能的微服务架构时&#xff0c;数据序列化和反序列化的性能至关重要。Protocol Buffers&#xff08;简称Protobuf&#xff09;作为一种轻量级且高效的结构化数据存储格式&#xff0c;已经在众多领域得到广泛应用。Gin框架作为Go语言中流行的Web框架&#xff0c;…