线程池 什么是线程池?
是一个抽象的概念, 若干个线程组合到一起, 形成线程池.
为什么需要线程池?
多线程版服务器一个客户端就需要创建一个线程! 若客户端太多, 显然不太合适.
什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了 。如果线程创建和销毁时间相比任务执行时间可以忽略不计,则没有必要使用线程池了 。
实现的时候类似于生产者和消费者.
线程池和任务池:
任务池相当于共享资源, 所以需要使用互斥锁, 当任务池中没有任务的时候需要让线程阻塞, 所以需要使用条件变量.
如何让线程执行不同的任务?
使用回到函数, 在任务中设置任务执行函数, 这样可以起到不同的任务执行不同的函数.
通过阅读线程池代码思考如下问题?
?熟悉结构体
?线程池如何创建起来? 各种初始化,,,
?线程池内都有几类线程? 2类:管理线程+工作线程
?管理者线程的任务是什么?任务如何实现? 任务是添加线程或者删除线程,通过2个算法,删除线程= 10
?工作线程如何工作? 等待有任务,抢到任务,修改 ++ 执行任务 修改–
?线程池是如何销毁的? 自爆 诱杀!
讲解代码.c
讲解代码 .c
.h
#ifndef _THREADPOOL_H#define _THREADPOOL_H#include #include #include #include #include
//简易版线程池
.c
#include "threadpoolsimple.h"ThreadPool *thrPool = NULL;int beginnum = 1000;void *thrRun(void *arg){//printf("begin call %s-----\n",__FUNCTION__);ThreadPool *pool = (ThreadPool*)arg;int taskpos = 0;//任务位置PoolTask *task = (PoolTask *)malloc(sizeof(PoolTask));while(1){//获取任务,先要尝试加锁pthread_mutex_lock(&thrPool->pool_lock);//无任务并且线程池不是要摧毁while(thrPool->job_num <= 0 && !thrPool->shutdown ){//如果没有任务,线程会阻塞pthread_cond_wait(&thrPool->not_empty_task,&thrPool->pool_lock);}if(thrPool->job_num){//有任务需要处理taskpos = (thrPool->job_pop++)%thrPool->max_job_num;//printf("task out %d...tasknum===%d tid=%lu\n",taskpos,thrPool->tasks[taskpos].tasknum,pthread_self());//为什么要拷贝?避免任务被修改,生产者会添加任务memcpy(task,&thrPool->tasks[taskpos],sizeof(PoolTask));task->arg = task;thrPool->job_num--;//task = &thrPool->tasks[taskpos];pthread_cond_signal(&thrPool->empty_task);//通知生产者}if(thrPool->shutdown){//代表要摧毁线程池,此时线程退出即可//pthread_detach(pthread_self());//临死前分家pthread_mutex_unlock(&thrPool->pool_lock);free(task);pthread_exit(NULL);}//释放锁pthread_mutex_unlock(&thrPool->pool_lock);task->task_func(task->arg);//执行回调函数}//printf("end call %s-----\n",__FUNCTION__);}//创建线程池void create_threadpool(int thrnum,int maxtasknum){printf("begin call %s-----\n",__FUNCTION__);thrPool = (ThreadPool*)malloc(sizeof(ThreadPool));thrPool->thr_num = thrnum;thrPool->max_job_num = maxtasknum;thrPool->shutdown = 0;//是否摧毁线程池,1代表摧毁thrPool->job_push = 0;//任务队列添加的位置thrPool->job_pop = 0;//任务队列出队的位置thrPool->job_num = 0;//初始化的任务个数为0thrPool->tasks = (PoolTask*)malloc((sizeof(PoolTask)*maxtasknum));//申请最大的任务队列//初始化锁和条件变量pthread_mutex_init(&thrPool->pool_lock,NULL);pthread_cond_init(&thrPool->empty_task,NULL);pthread_cond_init(&thrPool->not_empty_task,NULL);int i = 0;thrPool->threads = (pthread_t *)malloc(sizeof(pthread_t)*thrnum);//申请n个线程id的空间pthread_attr_t attr;pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);for(i = 0;i
- 动态行专列 【Mybatis实例】实现动态表头数据 、对动态表头字段排序
- 二 华为云上云实践:Linux 环境下对云硬盘 EVS 的创建、挂载和初始化
- 1 sklearn的学习笔记--决策树
- 如何让ChatGPT生成图片?
- 真土豪、IPO成功最高可获3730万奖励, 注册地迁移扶持2000万
- word表格的行高怎么调整
- Neo4j和Cypher快速入门
- 【go】go 实现行专列 将集合进行转列
- 如何将高德、百度、腾讯、必应、ArcGIS地图下载到本机?
- 一篇文章了解 Docker 的安装、启动以及工作原理!