线程池(thread pool)是一种多线程的处理形式,处理过程中将任务添加到队列,然后创建线程,启动并处理这些任务。
组成部分
服务器程序可以利用线程技术响应客户端请求。
1、线程池管理器:用于创建并管理线程
2、工作线程:正在处理任务的线程
3、任务接口:每个任务必须实现的借口,以供工作线程调度任务的执行
4、任务队列:用于存放没有被处理的任务。提供一种缓存机制。
线程池的实现
- 用于执行大量相对短暂的任务
- 当任务增加的时候能够动态的增加线程池中线程的数量直到到达一个阈值
- 当任务执行完毕的时候,能够动态的销毁线程池中的线程
- 该线程池的实现本质上也是生产者与消费者模型的应用。生产者线程向任务队列中添加任务,一旦队列有任务到来,如果有等待线程就唤醒来执行任务,如果没有等待线程并且线程数没有达到阈值,就创建新线程来执行任务。
1、下面是任务结构体的组成:
// 任务结构体,将任务放入队列由线程池中的线程执行
typedef struct task {
void *(*run)(void *arg); //任务回调函数
void *arg; //回调函数参数
struct task *next;
}task_t;
2、下面是线程池结构体的组成:
//线程池结构体
typedef struct threadpool {
condition_t ready; //任务准备就绪或者线程池销毁通知
task_t *first; //任务队列头指针
task_t *last; //任务队列尾指针
int counter; //线程池中当前线程数
int idle; //线程池中当前正在等待任务的线程数
int max_threads; //线程池中最大允许的线程数
int quit; //销毁线程池的时候置1
}threadpool_t;
3、线程池提供的接口函数
void threadpool_init (threadpool_t *pool, int threads); //初始化线程池
void threadpool_add_task (threadpool_t *pool, void *(*run) (void *arg), void *arg); //在线程池中添加任务
void threadpool_destroy(threadpool_t *pool); //销毁线程池
4、条件变量
#ifndef _CONDITION_H_
#define _CONDITION_H_
#include <pthread.h>
typedef struct condition{
pthread_mutex_t pmutex;
pthread_cond_t pcond;
}condition_t;
int condition_init(condition_t *cond);
int condition_lock(condition_t *cond);
int condition_unlock(condition_t *cond);
int condition_wait(condition_t *cond);
int condition_timedWait(condition_t *cond,const struct timespec *abstime);
int condition_signal(condition_t *cond);
int condition_broadcast(condition_t *cond);
int condition_destroy(condition_t *cond);
#endif /*_CONDITION_H_*/
5、条件变量的实现
#include "condition.h"
int condition_init(condition_t *cond)
{
int status;
if((status=pthread_mutex_init(&cond->pmutex,NULL)))
return status;
if((status=pthread_cond_init(&cond->pcond,NULL)))
return status;
return 0;
}
int condition_lock(condition_t *cond)
{
return pthread_mutex_lock(&cond->pmutex);
}
int condition_unlock(condition_t *cond)
{
return pthread_mutex_unlock(&cond->pmutex);
}
int condition_wait(condition_t *cond)
{
return pthread_cond_wait(&cond->pcond,&cond->pmutex);
}
int condition_timedWait(condition_t *cond,const struct timespec *abstime)
{
return pthread_cond_timedwait(&cond->pcond,&cond->pmutex,abstime);
}
int condition_signal(condition_t *cond)
{
return pthread_cond_signal(&cond->pcond);
}
int condition_broadcast(condition_t *cond)
{
return pthread_cond_broadcast(&cond->pcond);
}
int condition_destroy(condition_t *cond)
{
int status;
if((status=pthread_mutex_destroy(&cond->pmutex)))
return status;
if((status=pthread_cond_destroy(&cond->pcond)))
return status;
return 0;
}
6、线程池
#ifndef _THREAD_POOL_H_
#define _THREAD_POOL_H_
#include "condition.h"
typedef struct task
{
void *(*run)(void *arg);
void *arg;
struct task *next;
}task_t;
typedef struct threadpool
{
condition_t ready;
task_t *first;
task_t *last;
int counter;
int idle;
int max_threads;
int quit;
}threadpool_t;
void threadpool_init(threadpool_t *pool,int threads);
void threadpool_add_task(threadpool_t *pool,void *(*run)(void *arg),void *arg);
void threadpool_destroy(threadpool_t *pool);
#endif
7、线程池的实现
#include "threadpool.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
void *thread_routine(void *arg)
{
struct timespec abstime;
int timeout;
printf("thread 0x%x is starting\n",(int)pthread_self());
threadpool_t *pool=(threadpool_t*)arg;
while(1)
{
timeout=0;
condition_lock(&pool->ready);
pool->idle++;
//waiting the queue task or info of threadpool destroy
while(pool->first == NULL && !pool->quit)
{
printf("thread 0x%x is waiting\n",(int)pthread_self());
//condition_wait(&pool->ready);
clock_gettime(CLOCK_REALTIME,&abstime);
abstime.tv_sec+=2;
int status=condition_timedWait(&pool->ready,&abstime);
if(status==ETIMEDOUT)
{
printf("thread 0x%x is wait timed out\n",(int)pthread_self());
timeout=1;
break;
}
}
//waited the condition,on working
pool->idle--;
if(pool->first!=NULL)
{
//
task_t *t=pool->first;
pool->first=t->next;
condition_unlock(&pool->ready);
t->run(t->arg);
free(t);
condition_lock(&pool->ready);
}
if(pool->quit && pool->first==NULL)
{
pool->counter--;
if(pool->counter == 0)
condition_signal(&pool->ready);
condition_unlock(&pool->ready);
break;
}
if(timeout && pool->first == NULL)
{
pool->counter--;
condition_unlock(&pool->ready);
break;
}
condition_unlock(&pool->ready);
}
printf("thread 0x%x is exting\n" ,(int)pthread_self());
return NULL;
}
void threadpool_init(threadpool_t *pool,int threads)
{
condition_init(&pool->ready);
pool->first=NULL;
pool->last=NULL;
pool->counter=0;
pool->idle=0;
pool->max_threads=threads;
pool->quit=0;
}
void threadpool_add_task(threadpool_t *pool,void *(*run)(void *arg),void *arg)
{
//create new task
task_t *newtask=(task_t *)malloc(sizeof(task_t));
newtask->run=run;
newtask->arg=arg;
newtask->next=NULL;
condition_lock(&pool->ready);
//add new task to queue
if(pool->first==NULL)
pool->first=newtask;
else
pool->last->next=newtask;
pool->last=newtask;
//if there is a wait-pthread,then ex it
if(pool->idle>0)
{
condition_signal(&pool->ready);
}
else if(pool->counter<pool->max_threads)
{
//no wait-pthread and now the threads is not to max_threads
pthread_t tid;
pthread_create(&tid,NULL,thread_routine,pool);
pool->counter++;
}
condition_unlock(&pool->ready);
}
void threadpool_destroy(threadpool_t *pool)
{
if(pool->quit)
{
return;
}
condition_lock(&pool->ready);
pool->quit=1;
condition_unlock(&pool->ready);
if(pool->counter > 0)
{
if(pool->idle > 0)
condition_broadcast(&pool->ready);
while(pool->counter > 0)
{
condition_wait(&pool->ready);
}
condition_unlock(&pool->ready);
condition_destroy(&pool->ready);
}
}