线程池介绍线程池: 一种线程使用模式 。线程过多会带来调度开销,进而影响缓存局部性和整体性能 。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务 。这避免了在处理短时间任务时创建与销毁线程的代价 。线程池不仅能够保证内核的充分利用,还能防止过分调度 。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量
线程池的价值:
- 需要大量的线程来完成任务,且完成任务的时间比较短 。可同时处理多任务,多请求 。
- 有任务可以立即从线程池中调取线程取处理 , 节省了线程创建的时间
- 有效防止服务端线程过多而导致系统过载的问题
线程池的四个成员变量:
- 一个队列: 存放任务
- 线程池中线程数: 记录线程池中创建的线程数
- 互斥量: 一个互斥锁
- 条件变量: 两个条件变量
文章插图
线程池:首先需要创建几个线程,还有一个任务队列,当任务队列有任务的时候就唤醒一个正在等待的线程,让线程去执行任务,线程池中的线程执行完任务不会销毁,大大减少的cpu的消耗 。
需要两个条件变量和一个互斥锁 , 这个互斥锁用来锁住任务队列 , 因为任务队列是公共资源,其次还需要两个条件变量,一个条件变量用来阻塞取任务的线程,当队列中有任务的时候,直接取任务,然后解锁,当任务队列中没有任务的时候,解锁等待条件,条件满足抢锁 , 取任务 , 解锁 。另一个条件变量用来阻塞添加者进程,当任务队列满了,会让添加者进程等待,当有线程取走一个任务的时候,会唤醒添加者进程 。
版本一任务函数
这里的任务函数采用的时回调函数的方式,提高了代码的通用性 , 可以根据自己的需求改写任务函数
//任务回调函数void taskRun(void *arg){PoolTask *task = (PoolTask*)arg;int num = task->tasknum;printf("task %d is runing %lu\n",num,pthread_self());sleep(1);printf("task %d is done %lu\n",num,pthread_self());}
线程池的主要代码框架class ThreadPool{public://构造函数,初始化线程池ThreadPool(int thrnum, int maxtasknum){}static void* thrRun(void* arg){}//析构函数,摧毁线程池~ThreadPool(){}public://添加任务到线程池void addtask(){};private://任务队列相关的参数int max_job_num;//最大任务个数int job_num;//实际任务个数PoolTask *tasks;//任务队列数组int job_push;//入队位置int job_pop;// 出队位置//线程相关参数int thr_num;//线程池内线程个数pthread_t *threads;//线程池内线程数组int shutdown;//是否关闭线程池pthread_mutex_t pool_lock;//线程池的锁pthread_cond_t empty_task;//任务队列为空的条件pthread_cond_t not_empty_task;//任务队列不为空的条件};
放任务: 主线程无脑往任务队列中塞任务,塞任务之前进行加锁,塞完任务解锁,如果任务队列已经满了,等待线程取任务,然后唤醒在条件变量下等待的队列;放入了任务就给线程发送信号,唤醒线程来取取任务: 线程池中的线程从任务队列中取任务,需要对任务队列上锁,因为对公共资源的操作都需要上锁,如果没有任务就阻塞,等待放任务唤醒;如果取完了一个任务,就唤醒添加任务这就是两个条件变量和一个互斥锁的用法
//添加任务到线程池void addtask(){pthread_mutex_lock(&(this->pool_lock));//实际任务总数大于最大任务个数则阻塞等待(等待任务被处理)while(this->max_job_num <= this->job_num){pthread_cond_wait(&(this->empty_task),&(this->pool_lock));}int taskpos = (this->job_push++)%this->max_job_num;this->tasks[taskpos].tasknum = beginnum++;this->tasks[taskpos].arg = (void*)&this->tasks[taskpos];this->tasks[taskpos].task_func = taskRun;this->job_num++;pthread_mutex_unlock(&(this->pool_lock));pthread_cond_signal(&(this->not_empty_task));//通知包身工}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 明日方舟2022夏日嘉年华限定卡池有哪些角色
- 华为p50是曲面屏吗_直屏和曲屏有什么区别
- 地下城起源版本浓缩的异界精髓用法和获得方式
- 孩子沉迷于游戏和手机,作父母的该怎么办(孩子沉迷游戏爸妈束手无策)
- 五 AIR32F103 FreeRTOSv202112核心库的集成和示例代码
- .Net6新版本的AssemblyLoadContext 加载程序集和卸载程序集
- usmile大理石和微泡哪款好_usmile微泡刷和大理石版对比
- 支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程
- 常用Python库整理
- 天玑800U和骁龙768g哪个好_天玑800U和骁龙768g对比