为什么需要线程池:
现在大多数网络服务器,包括Web服务器,Email服务器以及数据库服务器等都具有一个共同点,就是单位时间内处理数目巨大的连接请求,但是处理时间却很短。
如果不用线程池,那么针对每一个请求,我们要花费时间如下
T1:线程创建时间
T2:线程执行时间,包括线程的同步等时间
T3:线程销毁时间
那么每一个线程我们都要话费他的创建时间和销毁时间,那么时间的花费就是(T1+T2)/(T1+T2+T3)若是线程执行时间短,那么这个开销的占比将会很大,而线程池的存在可以帮助我们大大的减少这些问题。
现在线程的机制如下:
首先预创建一些线程,放入空闲队列之中,这些线程都处于阻塞状态不消耗CPU,但占用较小的内存空间,当任务到来后,缓冲池选择一个空闲线程,把任务传入此线程中运行。
当预创建的线程消耗完毕的时候,线程池自动创建一定数量的新线程来处理更多的任务。
任务执行完毕后线程也不会消失,他会继续保持在线程池中等待下一次的任务,当系统比较空闲大部分线程处于暂停状态,线程池自动销毁一部分线程,回收系统资源。
线程池的大体框架:
(1)线程池管理器:创建并管理线程池
(2)工作线程:线程池中实际执行的线程
(3)任务接口:将线程执行的任务抽象出来,形成任务接口,从而使得线程池与具体的任务无关
(4)任务队列:线程池的概念具体到实现则可能是队列,链表之类的数据结构,其中保存执行队列
线程池的实现:
1.两个结构体,一个代表线程池,一个代表线程
typedef struct tpool_work {
8: void* (*routine)(void*); /* 任务函数 */
9: void *arg; /* 传入任务函数的参数 */
10: struct tpool_work *next;
11: }tpool_work_t;
12:
13: typedef struct tpool {
14: int shutdown; /* 线程池是否销毁 */
15: int max_thr_num; /* 最大线程数 */
16: pthread_t *thr_id; /* 线程ID数组 */
17: tpool_work_t *queue_head; /* 线程链表 */
18: pthread_mutex_t queue_lock;
19: pthread_cond_t queue_ready;
20: }tpool_t;
2.应当含有的函数
(1)线程池的创建
(2)线程池的销毁
(3)向线程池中添加任务(由于是线程,所以他的函数参数应该是void*(*routine)(void*))
相当于向任务链表加一个任务,记得通知任务链表条件变量状态idea变化
3.使用的需要的函数
(1)从任务链表取出任务执行
三种情况
(1)线程没有被销毁,没有任务要执行,那么就阻塞
(2)线程池被要求销毁那就销毁
(3)正常执行那么启用任务函数
需要注意的函数
pthread_cond_t cond;
pthread_cond_wait(&cond);
pthread_cond_signal(&cond);
pthread_cond_init(&cond,NULL);
pthread_cond_broadcast(&cond);
对着网上自己写的线程池,容量为6,然后最大活跃的也是6,但是执行10个任务,从输出可以看出来是有的执行完了就走了,然后之后来的任务在原先的内存继续执行
#include
#include
#include
#include
typedef struct thread
{
void* (*fun)(void* arg);
void* arg;
struct thread* next;
}thread;
typedef struct mypool
{
thread* list;//存放线程的任务链表
pthread_mutex_t mutex;//加锁防止线程之间陷入恶性竞争
pthread_cond_t cond;//条件变量,告诉我们什么时候线程需要被启用
int max_num;//线程池子中最大允许的线程个数
int cursize;//当前等待队列的任务数目
int shutdown;//标记线程池是否要被销毁
pthread_t *thid;//线程组ID
}Tpool;
static Tpool* pool = NULL;
//从任务队列中取出任务执行
static void* threadfun(void* arg)
{
thread* work;
while(1)
{
pthread_mutex_lock(&pool->mutex);
while(pool->cursize==0&&pool->shutdown!=1)//阻塞者
{
pthread_cond_wait(&pool->cond, &pool->mutex);
}
if(pool->shutdown == 1)
{
pthread_mutex_unlock(&pool->mutex);
printf("pthread exit!!!!!!!!!\n");
pthread_exit(NULL);
}
pool->cursize--;
work = pool->list;
pool->list = work->next;
pthread_mutex_unlock(&pool->mutex);
work->fun(work->arg);
free(work);
printf("执行一次任务,删除了一个工做\n");
}
return NULL;
}
void Initpool()//初始化线程池
{
pool = (Tpool*)malloc(sizeof(Tpool));
pool->max_num = 6;
pthread_mutex_init(&pool->mutex,NULL);
pthread_cond_init(&pool->cond,NULL);
pool->list = NULL;
pool->cursize = 0;
pool->thid = (pthread_t*)malloc(6*sizeof(thread));
int i= 0;
for(i;i<6;++i)
{
pthread_create(&pool->thid[i],NULL,threadfun,NULL);
}
}
void Destroy()
{
pool->shutdown = 1;
pthread_cond_broadcast(&pool->cond);
int i;
for(i=0;i
{
pthread_join(pool->thid[i],NULL);
}
free(pool->thid);
thread *member = NULL;
while(pool->list)
{
member = pool->list;
pool->list = pool->list->next;
free(member);
}
pthread_mutex_destroy(&pool->mutex);
pthread_cond_destroy(&pool->cond);
free(pool);
pool = NULL;
return ;
}
int pool_add_work(void*(*routine)(void*),void* arg)
{
thread* work,*member;
work = calloc(1,sizeof(thread));
work->fun = routine;
work->arg = arg;
work->next = NULL;
pthread_mutex_lock(&pool->mutex);
member = pool->list;
if(!member)//如果member是NULL
{
pool->list = work;
}
else
{
while(member->next)
{
member = member->next;
}
member->next = work;
}
//通知工作者线程有新任务添加
pool->cursize++;
pthread_cond_signal(&pool->cond);
pthread_mutex_unlock(&pool->mutex);
return 0;
}
void *func(void *arg)
{
printf("thread %d\n",(int)arg);
sleep(1);
return NULL;
}
int main(int arg, char **argv)
{
Initpool(pool);
int i= 0;
for(i;i<10;++i)
{
pool_add_work(func,(void*)i);
}
sleep(2);
Destroy();
return 0;
}