Linux - 线程池

embedded/2025/1/22 20:05:18/

线程池

什么是池?

池化技术的核心就是"提前准备并重复利用资源". 减少资源创建和销毁的成本.

那么线程池就是提前准备好一些线程, 当有任务来临时, 就可以直接交给这些线程运行, 当线程完成这些任务后, 并不会被销毁, 而是继续等待任务. 那么这些线程在程序运行过程中只需要创建一次. 相比当任务来临时创建线程, 当线程完成任务后销毁线程这种方法. 省去了很多线程创建销毁的成本.

一次性创建多个线程, 那么就需要将这些线程集中管理起来, 将这先线程集中起来并进行管理, 这样的集合就时线程池.

线程池实现

可以看到在线程池中, 我们至少需要对线程和任务进行管理

线程: 这里我们使用 vector 进行管理

任务: 这里使用 queue 对任务进行管理

首先对于传递给线程的数据先进行一步封装

class ThreadData
{
public:ThreadData(const std::string& name, void* arg):_name(name),_arg(arg){}std::string _name; // 本线程名称void* _arg; // 本线程所需(参数)数据
};

然后对线程也进行封装

class Thread
{
public:Thread(const int& num, const std::string& name, func_t func, void* arg):_num(num),_name(name),_func(func),_data(name, arg){}void start() // 只有调用 start 函数, 线程才会真正被创建{pthread_create(&_t, NULL, _func, (void*)&_data);}void join(){pthread_join(_t, NULL);}private:int _num; // 第几号线程pthread_t _t; // 线程的 pthread_tstd::string _name; // 线程名称func_t _func; // 线程要执行的函数ThreadData _data; // 线程所需要的参数(数据)
};

最后再是线程池 threadpool 代码.

#include<iostream>
#include<pthread.h>
#include<vector>
#include<queue>
#include<functional>
#include<unistd.h>// 对于线程要执行的函数的重命名
typedef void*(*func_t)(void*);class ThreadData
{
public:ThreadData(const std::string& name, void* arg):_name(name),_arg(arg){}std::string _name; // 本线程名称void* _arg; // 本线程所需数据
};class Thread
{
public:Thread(const int& num, const std::string& name, func_t func, void* arg):_num(num),_name(name),_func(func),_data(name, arg){}void start(){pthread_create(&_t, NULL, _func, (void*)&_data);}void join(){pthread_join(_t, NULL);}private:int _num; // 第几号线程pthread_t _t; // 线程的 pthread_tstd::string _name; // 线程名称func_t _func; // 线程要执行的函数ThreadData _data; // 线程所需要的参数(数据)
};template<class T>
class threadpool
{
public:threadpool(int num = 5){for(int i = 0; i < num; ++i){std::string name = "线程" + std::to_string(i);_threads.push_back(new Thread(i, name, route, (void*)this));}}void run() // 让线程池中的线程都被创建出来, 并运行起来{for(int i = 0; i < _threads.size(); ++i){_threads[i]->start();}}// 将数据放入线程池中void push(const T& data){pthread_mutex_lock(&_mtx);_tasks.push(data);pthread_mutex_unlock(&_mtx);pthread_cond_signal(&_cv);}// 析构函数~threadpool(){for(int i = 0; i < _threads.size(); ++i){_threads[i]->join();}}private:// 线程所要执行的函数// pthread_create 函数中, 传递给线程的函数类型就是 void*(*)(void*)// 如果这里不使用 static 静态函数, 而使用成员函数// 成员函数中默认会添加一个参数(this指针), 这样的化成员函数的类型就和 pthread_create 函数要求的类型不匹配static void* route(void* arg){// 从 Thread 的 start 函数中可以看到, 我们传递给函数的参数类型是 ThreadData*// 而 ThreadData 中的 _arg的实际类型, 通过 Thread 的构造函数和 run 函数可以看到// 给 ThreadData 的第二个参数实际上就 this 指针, this == threadpool<T>*// 所以 _arg 就是这个线程池对象的指针. 那么通过 _arg 也就能访问到// 线程池中的 _tasks. ThreadData* td = (ThreadData*)arg;threadpool<T>* tp = (threadpool<T>*)td->_arg;T task;while(true){// 获取数据pthread_mutex_lock(&tp->_mtx);while(tp->_tasks.empty() == true) // 如果没有数据了, 那么就进行等待{pthread_cond_wait(&tp->_cv, &tp->_mtx);}task = tp->_tasks.front();tp->_tasks.pop();pthread_mutex_unlock(&tp->_mtx);// 处理数据// 这里直接打印, 便于观察std::cout << td->_name << ": "<< task << std::endl;}return NULL;}private:std::vector<Thread*> _threads; // 管理所有的线程std::queue<T> _tasks; // 管理所有的任务pthread_mutex_t _mtx; // 线程间互斥的访问 _taskspthread_cond_t _cv; // 当 _tasks 中没有任务时, 让所有的线程进行等待, 直到被唤醒
};int main()
{threadpool<int> tp;tp.run();for(int i = 0; i < 10000; ++i){tp.push(i);}sleep(5);exit(0);return 0;
}

http://www.ppmy.cn/embedded/156141.html

相关文章

Oracle 创建并使用外部表

目录 一. 什么是外部表二. 创建外部表所在的文件夹对象三. 授予访问外部表文件夹的权限3.1 DBA用户授予普通用户访问外部表文件夹的权限3.2 授予Win10上的Oracle用户访问桌面文件夹的权限 四. 普通用户创建外部表五. 查询六. 删除 一. 什么是外部表 在 Oracle 数据库中&#x…

TCP如何保证安全可靠?

TCP如何保证安全可靠&#xff1f; TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、可靠的传输层协议。为了保证数据传输的安全性和可靠性&#xff0c;TCP 采用了多种机制&#xff0c;包括确认和重传、数据校验、数据分片和排序、流量控制以及拥塞控制。 1. 确认和…

【pytorch】norm的使用

torch.norm [deprecated ] 在torch.norm中&#xff0c;通过参数p来定制order 主要有如下几类 L1 norm 计算张量中所有数值之和L2 norm 计算张量中所有数值的平方和开根Frobenius norm 计算张量中所有维度上所有数值的平方和开根Infinity norm 计算张量中有所数值绝对值最大N…

Mysql触发器(学习自用)

一、介绍 二、触发器语法 注意&#xff1a;拿取新的数据时用new&#xff0c;旧数据用old。

Python----Python高级(模块与包,Python基本库)

一、模块 1.1、概念 就是一个包含了Python代码的以.py为后缀的Python文件&#xff0c;可以被其他 Python程序导入和使用&#xff0c;也可以自己独立执行&#xff0c;里面存放着的是一组相关的函 数或者类&#xff0c;比如查看关键字列表时导入的keyword模块。 1.2、作用 令Py…

科技护航:分布式 IO 模块与大型 PLC,稳筑地铁安全防线

在城市的地下脉络中&#xff0c;地铁如灵动的巨龙&#xff0c;承载着无数人的出行需求。保障地铁的稳定安全运行&#xff0c;是城市高效运转的关键&#xff0c;而这背后&#xff0c;分布式 IO 模块与大型 PLC 的默契协作&#xff0c;功不可没。 智慧大脑 大型 PLC&#xff0c;…

springboot使用ssl连接elasticsearch

使用es时ssl证书报错 unable to find valid certification path to requested target 1.依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>2…

解锁辅助驾驶新境界:基于昇腾 AI 异构计算架构 CANN 的应用探秘

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《AI大模型》 期待您的关注 目录 一、引言 二、CANN 是什么 1. 异构计算与人工智能的关系 2. CANN 的定义和作用 3. CANN 的技…