博客摘录「 【Linux】线程池」2023年10月14日

一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着 监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利 用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。我们去处理任务时,一个任务对应一个创建一个线程进行处理,效率是比较低的。我们可以预先创建一批线程,任务队列里没有任务的时候,每个线程都休眠,当队里中有任务的时候,就可以环形线程进行处理了。唤醒线程的成本比创建整个线程的成本小,这就是线程池的逻辑思想2.线程池的使用场景--  需要大量的线程来完成任务,且完成任务的时间比较短。--  对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。--  接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。3.实现线程池一.线程的封装Thread.hppThread类主要成员变量是线程名,函数,线程参数,参数ID以及对应编号Thread类提供了一个无参构造,完成对成员变量name的赋值。同时,对外主要提供了start接口和join接口,对于join接口就是线程等待,而对于start接口就是创建线程的接口,在外部如果调用的话我们需要传入对应的函数以及线程对应的参数。#pragma once#include <pthread.h>#include <iostream>#include <cassert>#include <string>#include <functional>namespace ThreadNs{ typedef std::function<void*(void*)> func_t; const int num =1024; class Thread { private: static void* start_routine(void*args) { Thread* _this = static_cast<Thread*>(args); return _this->callback(); } public: Thread() { char namebuffer[num]; snprintf(namebuffer,sizeof namebuffer,"thread-%d",threadnum++); name_ = namebuffer; } void start(func_t func,void*args = nullptr) { func_ = func; args_ = args; int n = pthread_create(&tid_,nullptr,start_routine,this); assert(n==0); (void)n; } void join() { int n = pthread_join(tid_,nullptr); assert(n==0); (void)n; } std::string threadname() { return name_; } ~Thread() {} void* callback() { return func_(args_); } private: std::string name_; func_t func_; void *args_; pthread_t tid_; static int threadnum; }; int Thread::threadnum = 1;} 对于任务队列,可以由多个线程进行访问所以要加锁保护,下面是对锁的封装:LockGuard.hpp:#include <iostream>#include <mutex>class Mutex{public: Mutex(pthread_mutex_t*lock_p=nullptr) :lock_p_(lock_p) {} void lock() { if(lock_p_) pthread_mutex_lock(lock_p_); } void unlock() { if(lock_p_) pthread_mutex_unlock(lock_p_); } ~Mutex() {}private: pthread_mutex_t * lock_p_;};class LockGuard{public: LockGuard(pthread_mutex_t*mutex) :mutex_(mutex) { mutex_.lock(); } ~LockGuard() { mutex_.unlock(); }private: Mutex mutex_;};创建一批线程时,我们需要实现线程的调用函数static void*handlerTask,之所以是静态的,是因为我们要把这个运行函数传递给Thread类中的func_,不能有this指针,所以是静态成员函数。而没有this指针,我们无法访问ThreadPool里面的成员变量,所以需要封装接口供其调用。ThreadPool.hpp#pragma once#include "Thread.hpp"#include "LockGuard.hpp"#include <vector>#include <queue>#include <pthread.h>#include <mutex>#include <unistd.h>using namespace ThreadNs;const int gnum = 3;template <class T>class ThreadPool; template <class T>class ThreadData{public: ThreadPool<T> *threadpool; std::string name;public: ThreadData(ThreadPool<T> *tp, const std::string &n) : threadpool(tp), name(n) { }};template <class T>class ThreadPool{private: static void *handlerTask(void *args) { ThreadData<T> *td = (ThreadData<T> *)args; ThreadPool<T> *threadpool = static_cast<ThreadPool<T> *>(args); while (true) { T t; { LockGuard lockguard(td->threadpool->mutex()); while(td->threadpool->isQueueEmpty()) { td->threadpool->threadWait(); } t = td->threadpool->pop(); } std::cout << td->name << " 获取了一个任务" << t.toTaskString() << "并处理完成,结果是: " << t() << std::endl; } delete td; return nullptr; }public: void lockQueue() { pthread_mutex_lock(&_mutex); } void unlockQueue() { pthread_mutex_unlock(&_mutex); } bool isQueueEmpty() { return _task_queue.empty(); } void threadWait() { pthread_cond_wait(&_cond, &_mutex); } T pop() { T t = _task_queue.front(); _task_queue.pop(); return t; } void Push(const T &in) { LockGuard lockguard(&_mutex); _task_queue.push(in); pthread_cond_signal(&_cond); } pthread_mutex_t *mutex() { return &_mutex; } public: ThreadPool(const int &num = gnum) : _num(num) { pthread_mutex_init(&_mutex, nullptr); pthread_cond_init(&_cond, nullptr); for (int i = 0; i < _num; i++) { _threads.push_back(new Thread()); } } void run() { for (const auto &t : _threads) { ThreadData<T> *td = new ThreadData<T>(this, t->threadname()); t->start(handlerTask, td); std::cout << t->threadname() << "start..." << std::endl; } } ~ThreadPool() { pthread_mutex_destroy(&_mutex); pthread_cond_destroy(&_cond); for (const auto &t : _threads) delete t; }private: int _num; std::vector<Thread *> _threads; std::queue<T> _task_queue; pthread_mutex_t _mutex; pthread_cond_t _cond;};因为线程池中存储的任务是任意的,所以需要将线程池进行模板化,下面引入任务组件Task.hpp#pragma once#include <iostream>#include <functional>class Task{ using func_t = std::function<int(int,int ,char)>;public: Task(){} Task(int x,int y,char op,func_t func) :_x(x),_y(y),_op(op),_callback(func) {} std::string operator()() { int result = _callback(_x,_y,_op); char buffer[1024]; snprintf(buffer,sizeof buffer,"%d %c %d = %d",_x,_op,_y,result); return buffer; } std::string toTaskString() { char buffer[1024]; snprintf(buffer,sizeof buffer,"%d %c %d = ?",_x,_op,_y); return buffer; }private: int _x; int _y; char _op; func_t _callback;}; const std::string oper = "+-*/%";int mymath(int x,int y,char op){ int result = 0; switch(op) { case '+': result = x+y; break; case '-': result = x-y; break; case '*': result = x*y; break; case '/': if(y==0) { std::cerr<<"div zero error!"<<std::endl; result = -1; } else { result = x/y; } break; case '%': if(y==0) { std::cerr<<"mod zero error!"<<std::endl; result = -1; } else { result = x%y; } break; default: break; } return result;}main.cpp#include "ThreadPool.hpp"#include "Thread.hpp"#include "Task.hpp"#include <unistd.h>#include <ctime>int main(){ ThreadPool<Task>* tp = new ThreadPool<Task>(); tp->run(); srand(time(0)); int x,y; char op; while(true) { x = rand()%10+1; y = rand()%20+1; op =oper[rand()%oper.size()]; Task t(x,y,op,mymath); tp->Push(t); sleep(1); } return 0;}文章知识点与官方知识档案匹配,可进一步学习相关知识CS入门技能树Linux入门初识Linux35683 人正在系统学习中阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作bite-ccc关注854『Linux』第九讲:Linux多线程详解(六 - 完结)_ 线程池 | 读写锁枫叶先生的博客 678线程池 | 读写锁详解Linux组件之线程池Ricardo2的博客 357手写线程池4 条评论微风撞见云热评支持博主优质文章,讲解得非常透彻,解答了我许多疑惑!写评论Linux —— 线程池M的博客 4395一、什么是线程池二、线程池的优点三、线程池的应用四、实现一个简单的线程池五、单例模式1. 饿汉实现方式2. 懒汉实现方式3. 单例模式实现线程池(懒汉方式)六、其他常见的各种锁【Linux线程池】qq_68472674的博客 129Linux线程池linux 实现一个简单的线程池及工作03-30linux 实现一个简单的线程池及工作 本实例演示了线程池的创建使用线程池【Linux】Man9o 5151. 引入 2. 应用 3. 实现 封装线程 封装线程池 线程函数 生产消费逻辑 互斥锁 条件变量 线程函数 主线程 测试1 4. 优化 5. 日志 日志的重要性 实现 日志级别 提取参数 stdarg.h 头文件 日志文件 懒汉实现单例模式 什么是懒汉模式 什么是单例模式 实现linux c线程池10-15linux pthreadpool实现和线程池的用处 简单易懂 互斥和信号量使用Linux--线程池与进程池及线程池的简单实现热门推荐sayhello_world的博客 1万+池由于服务器的硬件资源“充裕”,那么提高服务器性能的一个很直接的方法就是以空间换时间,即“浪费”服务器的硬件资源,以换取其运行效率。这就是池的概念。池是一组资源的集合,这组资源在服务器启动之初就被创建并初始化,这称为静态资源分配。当服务器进入正式运行阶段,即开始处理客户请求的时候,如果它需要相关的资源,就可以直接从池中获取,无需动态分配。很显然,直接从池中取得所需资源比动态分配资源的速度要快得多,因Linux下C线程池实现05-05在Linux下用C写的一个简易线程池。系统是RedHat 9,gcc版本"gcc version 4.1.2 20071124 (Red Hat 4.1.2-42)"。文件夹里的源码是按工程组织好的,在文件夹下的test目录下面有一个小的测试程序和Makefile,编译后即可运行。测试过添加了300多个任务,同时并发256个线程,运行正常。不过在停止线程(包括系统空闲时减少线程数量)方面还没完全实现好,需要用的话可以自己添加或者暂时先不管这方面。 补充:利用7号中午的时间已经把上述的问题解决了,现已能正确的根据当前任务数动态减少线程。不过现在不方便也不想上传了,需要的话可以通过源文件中的邮箱联系我或在以后去google code下载。如果各位有好的建议,欢迎通过邮件联系。 -------- by vincentlinux线程池,c语言实现01-06linux线程池,c语言实现,只是文件后缀名用的是cpp方便在qt里面测试,两种版本,都是参考网上的资料做了一些处理之后的Linux线程池11-24在Linux下运用Boost来实现的一个线程池,方便而且高效linux线程池创建c实现07-23linux线程池创建c实现 linux线程池创建c实现 linux线程池创建c实现 linux线程池创建c实现 linux线程池创建c实现 linux线程池创建c实现Linux 线程池源码分析11-12非常详细的线程池函数接口分析,可以帮助初学者加深对线程池的理解,更好的去把线程池运用到实例中去,线程池就是多个线程组合在一起的集合,就像一家公司一样,由多个员工组成的一个集合,当有任务时, 这些线程就会去处理任务,当没有任务时,线程就会休息。Linux下线程池(ThreadPool)qq_56999918的博客 796再这里实现的是一个简单的线程池,再这个线程池当中有一个任务队列,线程从任务队列当中提前任务,已经若干个线程,一开始再特点的条件变量下进行等待。线程池中的线程去这个任务队列当中拿任务的前提必须是任务队列当中要有任务,如果此时我们只使用互斥锁那么就有可能出现互斥锁一直被一个线程占用着,这是不合理的因此我们需要引入条件变量。此时线程池中的线程只需要从任务队列中拿到任务然后执行Run方法即可.下面我们来看一下主线程的执行逻辑:主线程主要负责通过线程池提供的Push方法将任务放入到任务队列当中即可。Linux 线程池09-03可实现线程池的基本功能,用多线程实现对文件的读取,可读取大文件,经实测代码没有任何bugLinux线程池代码.zip11-14基于Linux的线程池源代码linux线程池代码(c++实现)04-15linux线程池代码(c++实现) 分两部: 1、创建线程池 2、创建任务、加入线程池 可以参考使用linux线程池实现数据拷贝05-141、使用线程池的概念,利用linux多线程对一个目录以及目录中嵌套的文件进行拷贝,保证拷贝数据的完整性,并且多线程并发进行拷贝,节约程序运行时间,提高工作效率。 2、涉及linux文件IO、linux多线程&线程池、数据...linux线程池原理最新发布07-28Linux线程池的原理是通过任务队列和线程队列的配合来实现的。任务队列用于存储需要处理的任务,而线程队列则用于存储可用的线程。当有任务需要处理时,线程池会从线程队列中获取一个空闲线程来执行任务。当任务执行完毕后,线程会返回线程队列,等待下一个任务的到来。 线程池的初始化过程包括申请内存、初始化锁和信号量、设置最大线程数量、最大空闲线程数量等。在初始化完成后,线程池就可以开始接收任务并进行处理了。 在任务执行函数中,线程会从任务队列中获取任务,并执行相应的操作。当任务执行完毕后,线程会继续等待下一个任务的到来。需要注意的是,在线程退出后,线程节点的内存并没有归还给操作系统,这是因为设计相对简单,可以根据需要进行改进。 总结来说,Linux线程池的原理是通过任务队列和线程队列的配合来实现任务的分配和执行。这种设计可以提高程序的效率和性能,同时也可以避免频繁地创建和销毁线程。112233#### 引用[.reference_title] - *1* [linux下c语言版线程池](https://blog.csdn.net/weixin_42398658/article/details/123849826)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Linux线程池的原理及实现](https://blog.csdn.net/weixin_44344462/article/details/96432009)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

相关文章

Vue公共loading升级版(处理并发异步差时响应)

公共loading是项目系统中很常见的场景&#xff0c;处理方式也不外乎三个步骤&#xff1a; 通过全局状态管理定义状态值&#xff08;vuex、pinia等&#xff09;。 在程序主入口监听状态值变化&#xff0c;从而展示/隐藏laoding动画。 在请求和相应拦截器中变更状态值。 第一二…

svn文件不显示红色感叹号

如下图所示&#xff0c;受svn版本控制的文件不显示下图中红色感叹号和绿色对号时&#xff0c; 可以试着如下操作 空白处单击右键&#xff0c;具体操作如下图

Rust可空类型Option

文章目录 Option基础模式匹配unwrap Rust基础教程&#xff1a;初步⚙所有权⚙结构体和枚举类⚙函数进阶⚙泛型和特征⚙并发和线程通信⚙cargo包管理 Rust进阶教程&#xff1a;用宏实现参数可变的函数⚙类函数宏 Option基础 在一些编程语言中&#xff0c;允许存在空值&#xf…

docker的基本使用以及使用Docker 运行D435i

1.一些基本的指令 1.1 容器 要查看正在运行的容器&#xff1a; sudo docker ps 查看所有的容器&#xff08;包括停止状态的容器&#xff09; sudo docker ps -a 重新命名容器 sudo docker rename <old_name> <new_name> <old_name> 替换为你的容器名称…

用 HLS 实现 UART

用 HLS 实现 UART 介绍 UART 是一种旧的串行通信机制&#xff0c;但仍在很多平台中使用。它在 HDL 语言中的实现并不棘手&#xff0c;可以被视为本科生的作业。在这里&#xff0c;我将通过这个例子来展示在 HLS 中实现它是多么容易和有趣。 因此&#xff0c;从概念上讲&#xf…

内存池的面试整理

文章思路来源 如何实现无锁申请&#xff1f; 每个线程申请自己的TreadCacheTLS对象&#xff0c;来管理自己的freeList数组。小内存的大小&#xff1f; 0-256K&#xff0c;并且对申请到的内存进行字节对齐&#xff0c;保证申请到的内存可以映射到对应的freeList中。映射规则&am…

Linux命令(129)之dstat

linux命令之dstat 1.dstat介绍 linux命令dstat是用来实时显示系统中各个进程的资源占用情况 2.dstat用法 dstat [参数] dstat参数 参数说明-c显示CPU的相关信息-d显示磁盘的相关信息-g显示page相关的统计数据-m显示内存的相关统计数据-n显示网络的相关统计数据-p显示进程的…

配置你的VsCode服务器,随时随地写代码!

Hello&#xff0c;大家好&#xff0c;好久不见&#xff01;前段时间忙着秋招和论文&#xff0c;临近秋招结束&#xff0c;终于有时间更新了 前段时间实验室搞一个4090服务器&#xff0c;终于可以无所忌惮地跑深度学习咯&#xff0c;刚好要配置环境&#xff0c;今天就教大家通…

Unity收费对谁影响最大

Unity的收费政策对以下几类人群影响最大&#xff1a; 游戏开发商&#xff1a;Unity收费政策中最直接的影响对象就是游戏开发商。对于那些使用Unity引擎制作游戏的开发商来说&#xff0c;他们将需要考虑新的许可证费用和服务费用&#xff0c;这可能会对他们的盈利和发展产生影响…

EASYEXCEL(一)

1.读取excel 读监听器 Slf4j public class StudentReadListener extends AnalysisEventListener<Student> {// 每读一样&#xff0c;会调用该invoke方法一次Overridepublic void invoke(Student data, AnalysisContext context) {System.out.println("data "…

Linux MYSQL-5.7.23-rpm安装(附带安装包)

系统环境 OS 版本(Linux) CentOS-7-x86_64-Minimal-1511Java版本 jdk1.7及以上 卸载系统自带mariadb-lib rpm -qa|grep mariadbrpm -e mariadb-libs-5.5.68-1.el7.x86_64 --nodeps解压tar包 tar -xvf mysql*.tar以下加粗rpm包需要安装&#xff1a; mysql-community-common…

LeetCode26.删除有序数组中的重复项(双指针法)

LeetCode26.删除有序数组中的重复项 1.问题描述2.解题思路3.代码 1.问题描述 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返…

php怎么检测字符串是否只含数字

1、用is_numeric()检测一个字符串是否为数字字符串&#xff0c;语法“is_numeric (字符串)”&#xff0c;如果返回TRUE则只含数字,带小数点的也是数字类型 is_numeric(a123) //false is_numeric(123) //true is_numeric(3.14) //true2、用preg_replace()配合正则表达式过滤字符…

基于SSM的学院网站设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

Transformers实战——多项选择

文章目录 一、导入相关包二、加载数据集三、数据集预处理四、创建模型五、创建评估函数六、配置训练参数七、创建训练器八、模型训练九、模型预测 !pip install transformers datasets evaluate accelerate 一、导入相关包 import evaluate from datasets import DatasetDict,…

用ScheduledExecutorService接口,Quartz框架等创建定时任务

【点我-这里送书】 本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(…

小程序常见操作

测试时访问本地http服务器调用报错 微信开发者工具&#xff08;右上角&#xff09;-> 详情->本地设置->不校验合法域名、web-view(业务域名)... -> 去除勾选使用npm包 1) 工程目录下创建package.jsonnpm init(手动完成设定) / npm init -y (默认设定) 2) 安装 np…

SAP权限相关的表及如何使用FM获取用户权限

一、SAP权限相关的表 AGR_1016 活动组参数文件名称 AGR_1016B 活动组参数文件名称 AGR_1250 活动组的权限数据(通过权限对象 查 角色) AGR_1251 活动组的权限数据 AGR_1252 …

AVR单片机在机器人视觉导航中的应用研究

AVR单片机在机器人视觉导航中的应用是一项前沿的研究领域&#xff0c;旨在实现机器人在未知环境中的自主导航和避障功能。本文将介绍AVR单片机在机器人视觉导航中的应用原理和实现步骤&#xff0c;并提供相应的代码示例。 1. 导航概述 机器人视觉导航是基于计算机视觉和控制理…

SpringBoot 整合 JdbcTemplate(配置多数据源)

数据持久化有几个常见的方案&#xff0c;有 Spring 自带的 JdbcTemplate 、有 MyBatis&#xff0c;还有 JPA&#xff0c;在这些方案中&#xff0c;最简单的就是 Spring 自带的 JdbcTemplate 了&#xff0c;这个东西虽然没有 MyBatis 那么方便&#xff0c;但是比起最开始的 Jdbc…