C++的并发世界(十一)——线程池

news2024/10/6 20:33:22

0.线程池的概念

在这里插入图片描述

1.线程池使用步骤

①初始化线程池:确定线程数量,并做好互斥访问;
②启动所有线程
③准备好任务处理基类;
④获取任务接口:通过条件变量阻塞等待任务

2.atomic原子操作

'std:atomic`是C++11标准库中的一个模板类,用于实现多线程环境下的原子操作。它提供了一种线程安全的方式来访问和修改共享变量,可以避免多线程环境中的数据竞争问题,'std:atomic’的使用方式类似于普通的C++变量,但是它的操作是原子性的。也就是说,在多线程环境下,多个线程同时对同一个’std:atomic变量进行操作时,不会出现数据竞争问题。

3.线程池案例

①threadpool.cpp

#include "threadpool.h"


void XThreadPool::Init(int num)
{
	std::unique_lock<std::mutex> lock(__mux__);
	thread_num = num;
	std::cout << "Thread pool Init: " << num << std::endl;
}


void XThreadPool::Start()
{
	std::unique_lock<std::mutex> lock(__mux__);
	
	if (thread_num <= 0)
	{
		std::cerr << "Please Init XThreadPool !" << std::endl;
		return;
	}

	if (!threads.empty())
	{
		std::cerr << "Thread Pool has start!" << std::endl;
		return;
	}

	for (int i = 0; i < thread_num; i++)
	{
		auto th = std::make_shared<std::thread>(&XThreadPool::Run, this);
		threads.push_back(th);
	}
}

void XThreadPool::Run()
{
	std::cout << "begin XThreadPool Run: " << std::this_thread::get_id() << std::endl;
	
	while (true)
	{
		auto task = GetTask();
		if (!task)
		{
			continue;
		}
		
		++__task_run_count__;

		try
		{
			auto re = task->Run();
			task->Setvalue(re);
		}
		catch (...)
		{
			
		}
		--__task_run_count__;
	}

	std::cout << "end XThreadPool Run: " << std::this_thread::get_id() << std::endl;
}

void XThreadPool::AddTask(XTask *task)
{
	std::unique_lock<std::mutex> lock(__mux__);
	tasks.push_back(task);
	task->is_exit = [this] {return is_exit(); }
}

XTask* XThreadPool::GetTask()
{
	std::unique_lock<std::mutex> lock(__mux__);
	if (tasks.empty())
	{
		__cv__.wait(lock);
	}

	auto task = tasks.front();
	tasks.pop_front();
	return task;
}

void XThreadPool::Stop()
{
	exit = true;
	__cv__.notify_all();
	for (auto &th : threads)
	{
		th->join();
	}

	std::unique_lock<std::mutex> lock(__mux__);
	threads.clear();
}

②threadpool.h

#pragma once

#include <thread>
#include <mutex>
#include <vector>
#include <list>
#include <iostream>
#include <string>
#include <condition_variable>
#include <functional>
#include <atomic>
#include <future>

class XTask
{
	public:
		virtual int Run() = 0;
		std::function<bool()> is_exit = nullptr;
		void Setvalue(int v) { __p__.set_value(v); }
		auto GetValue() { return __p__.get_future().get(); }
	private:
		std::promise<int> __p__;//用来接收返回值
};

class XThreadPool
{
	public:
		void Init(int num);
		void Start();//所有线程启动函数
		void Stop();//线程池退出
		void AddTask(XTask *task);
		XTask* GetTask();
		bool is_exit() { return exit; }
		int task_run_count() { return __task_run_count__; }

	private:
		int thread_num = 0;
		std::mutex __mux__;
		void Run();//线程池线程入口函数
		std::vector<std::shared_ptr<std::thread>> threads;
		std::list<XTask*> tasks;
		std::condition_variable __cv__;
		bool exit = false;
		std::atomic<int> __task_run_count__ = {0};//正在运行的任务数量
};

③main.cpp

#include "threadpool.h"

class MyTask :public XTask
{
	public:
		int Run()
		{
			std::cout <<"==============================================" << std::endl;
			std::cout << std::this_thread::get_id() << "-Mytask" << name << std::endl;
			std::cout << "==============================================" << std::endl;

			for (int i = 0; i < 10; i++)
			{
				if(is_exit())
				{
					break;
				}

				std::cout << "." << std::flush;
				std::this_thread::sleep_for(std::chrono::microseconds(500));
			}

			return 0;
		}

		std::string name = "";
};

int main()
{
	XThreadPool pool;
	pool.Init(16);
	pool.Start();

	MyTask task1;
	task1.name = "test name 001";
	pool.AddTask(&task1);

	MyTask task2;
	task2.name = "test name 002";
	pool.AddTask(&task2);
	std::this_thread::sleep_for(std::chrono::seconds(100));
	std::cout << "task run count =" << pool.task_run_count() << std::endl;

	MyTask task3;
	task3.name = "test name 003";
	pool.AddTask(&task3);

	MyTask task4;
	task4.name = "test name 004";
	pool.AddTask(&task4);
	std::cout << "task run count = " << pool.task_run_count() << std::endl;

	std::this_thread::sleep_for(std::chrono::seconds(1));
	pool.Stop();
	std::cout << "task run count =" << pool.task_run_count() << std::endl;

	getchar();
	return 0;
}

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

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

相关文章

双碳目标下太阳辐射预报模式【WRF-SOLAR】及改进技术在气象、农林、电力等相关领域中的应用

太阳能是一种清洁能源&#xff0c;合理有效开发太阳能资源对减少污染、保护环境以及应对气候变化和能源安全具有非常重要的实际意义&#xff0c;为了实现能源和环境的可持续发展&#xff0c;近年来世界各国都高度重视太阳能资源的开发利用&#xff1b;另外太阳辐射的光谱成分、…

A Note on LoRA

A Note on LoRA 摘要Additional InsightsPractical ImprovementsLooking Ahead 摘要 LoRA已成为一种首选的方法&#xff0c;用以高效地适应大型语言模型&#xff08;LLM&#xff09;&#xff0c;其简便性和有效性令人瞩目。本文档扩展了原始LoRA论文&#xff0c;提供了最初未讨…

Spring中的适配器模式

在Spring MVC框架中&#xff0c;适配器模式主要体现在对不同类型的处理器&#xff08;即Controller&#xff09;的统一处理上。Spring MVC通过适配器模式来保证无论Controller的实现方式如何多样化&#xff0c;都能够被DispatcherServlet统一调用和管理。具体使用方式如下&…

李廉洋:4.10黄金原油晚间走势最新分析及策略。

鉴于美联储官员对1月和2月通胀数据反应不足&#xff0c;3月通胀数据过热可能导致其反应过度的风险更大。美联储试图避免根据一两个数据点来制定政策&#xff0c;但今年迄今为止经济活动的韧性意味着&#xff0c;在年中降息的理由取决于通胀是否恢复自去年下半年以来的稳步下降趋…

uniapp小程序编译报错

说明 微信小程序编译每次都出现[ project.config.json 文件内容错误] project.config.json: libVersion 字段需为 string, 解决 找到manifest.json文件 添加&#xff1a;"libVersion": "latest"&#xff0c;重新编译即可。

Redis常见数据类型(2)

目录 String字符串 常见命令 SET GET MGET MSET SETNX 计数命令 INCR INCRBY DECR DECRBY INCRFLOAT 其它命令 APPEND GETRANGE SETRANGE STRLEN String字符串 字符串是Redis最基础的数据类型, 关于字符串需要特别注意: (1)首先Redis中所有的键的类型都是字符…

[leetcode]remove-duplicates-from-sorted-list-ii

. - 力扣&#xff08;LeetCode&#xff09; 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,3,4,4,5] 输出&#xff1a;[1,2,5]示例 2&…

jvm中jdk常用的几个命令总结

1.jmap 此命令可以用来查询内存信息&#xff0c;实例个数及占用内存大小 1.1 查看堆内存概要信息&#xff08;内存分配统计&#xff09; jmap -histo[:live] <pid> .-histo&#xff1a;显示堆中对象的统计信息&#xff0c;包括每个类的实例数量、占用内存大小等 :live…

互联网产品经理必备知识详解

1. 前言 本文档全面探讨了产品经理在产品管理过程中的关键环节,包括市场调研、产品定义及设计、项目管理、产品宣介、产品市场以及产品生命周期。通过深入剖析这些方面,本文旨在帮助产品经理系统地理解和掌握产品管理的核心要素,从而提升产品开发的效率和成功率。在市场调研…

HarmonyOS 开发-二级联动

介绍 本示例主要介绍了List组件实现二级联动&#xff08;Cascading List&#xff09;的场景。 该场景多用于短视频中拍摄风格的选择、照片编辑时的场景的选择。 效果图预览 使用说明&#xff1a; 滑动二级列表侧控件&#xff0c;一级列表随之滚动。点击一级列表&#xff0c;…

运行vue项目

将命令改为&#xff1a; 1 npm run dev vite 不是内部分外部命令 报错信息&#xff1a;"vite 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件" 通常意味着 Vite 没有被安装或者没有正确地添加到系统的环境变量中。 解决方法&#xff1a; 确认 V…

HAL ST32F4 定时器2触发ADC转换

HAL ST32F4 定时器2触发ADC转换 &#x1f4cd;相关篇《STM32 F401/411外设内部互联矩阵摘要》《STM32G070RBT6基于STM32CubeMX创建ADC DMA多通道采样工程》 &#x1f4dd;利用定时器2的更新中断触发ADC转换。与定时器中断中调用ADC转换不同。前者是内部更新事件触发ADC转换&…

美团一面,面试官让介绍AQS原理并手写一个同步器,直接凉了

写在开头 今天在牛客上看到了一个帖子&#xff0c;一个网友吐槽美团一面上来就让手撕同步器&#xff0c;没整出来&#xff0c;结果面试直接凉凉。 就此联想到一周前写的一篇关于AQS知识点解析的博文&#xff0c;当时也曾埋下伏笔说后面会根据AQS的原理实现一个自定义的同步器…

05 Php学习:类型比较、常量

PHP 类型比较 虽然 PHP 是弱类型语言&#xff0c;但也需要明白变量类型及它们的意义&#xff0c;因为我们经常需要对 PHP 变量进行比较&#xff0c;包含松散和严格比较。 松散比较&#xff1a;使用两个等号 比较&#xff0c;只比较值&#xff0c;不比较类型。严格比较&#x…

<网络> 网络Socket编程基于TCP协议模拟简易网络通信

目录​​​​​​​ 前言&#xff1a; 一、字符串回响 &#xff08;一&#xff09;程序结构 &#xff08;二&#xff09;初始化服务器 &#xff08;三&#xff09;启动服务器 1. 处理连接请求 2. 业务处理 3. 回调函数 &#xff08;四&#xff09;填充server源文件 &…

pyqt5 QScrollArea组件

本示例中&#xff0c;演示了QScrollArea的使用&#xff0c;以及QScrollBar的样式设定&#xff0c;在代码中使用setStyleSheet设置样式&#xff0c;记得要优先设置scrollArea&#xff0c;再设置窗口的样式&#xff0c;不然QScrollBar的样式会不起作用&#xff0c;使用QSS设置没有…

【讲解下Fiddler的安装和使用】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

基于Java+SpringBoot+Vue文学名著分享系统(源码+文档+部署+讲解)

一.系统概述 随着世界经济信息化、全球化的到来和互联网的飞速发展&#xff0c;推动了各行业的改革。若想达到安全&#xff0c;快捷的目的&#xff0c;就需要拥有信息化的组织和管理模式&#xff0c;建立一套合理、动态的、交互友好的、高效的文学名著分享系统。当前的信息管理…

接口自动化测试(python+pytest+requests)

一、选取自动化测试用例 优先级高:先实现业务流程用例、后实现单接口用例功能较稳定的接口优先开展测试用例脚本的实现二、搭建自动化测试环境 核心技术:编程语言:python;测试框架:pytest;接口请求:requests安装/验证requests:命令行终端分别输入 pip install requests / p…

LMDoply部署实战

使用LMDeoply部署各类开源大模型&#xff0c;进行推理实践。 一. 环境准备 1. 创建Conda环境 studio-conda -t lmdeploy -o pytorch-2.1.2 2. 安装LMDeploy 激活刚刚创建的虚拟环境。 conda activate lmdeploy 安装0.3.0版本的lmdeploy。 pip install lmdeploy[all]0.3.…