由一个任务队列和一组处理队列的线程组成。一旦工作进程需要处理某个可能“阻塞”的操作,不用自己操作,将其作为一个任务放到线程池的队列,接着会被某个空闲线程提取处理。
任务 待处理的工作,通常由标识、上下文和处理函数组成。
任务队列 按顺序保存待处理的任务序列,等待线程中的线程组处理。
线程池 由多个已启动的一组线程组成。
条件变量 一种同步机制,允许线程挂起,直到共享数据上的某些条件得到满足。
互斥锁 保证在任一时刻,只能有一个线程访问该对象。
#ifndef _DEMO_THREAD_H_INCLUDED_
#define _DEMO_THREAD_H_INCLUDED_
#include
#include
#include
#include
#include
#include
#include
typedef intptr_t int_t;
typedef uintptr_t uint_t;
#define OK 0
#define ERROR -1
//---------互斥量(互斥锁)接口的封装-----------定义:thread_mutex.c
int thread_mutex_create(pthread_mutex_t *mtx); //线程 互斥锁的 创建
int thread_mutex_destroy(pthread_mutex_t *mtx); //线程 互斥锁的 销毁
int thread_mutex_lock(pthread_mutex_t *mtx); //线程 互斥锁的 加锁
int thread_mutex_unlock(pthread_mutex_t *mtx); //线程 互斥锁的 解锁
//---------条件变量接口的封装-----------------定义:thread_cond.c
int thread_cond_create(pthread_cond_t *cond); //线程 条件变量的 创建
int thread_cond_destroy(pthread_cond_t *cond); //线程 条件变量的 销毁
int thread_cond_signal(pthread_cond_t *cond); //线程 条件变量的 信号发送
int thread_cond_wait(pthread_cond_t *cond, //线程 条件变量的 信号接受
pthread_mutex_t *mtx);
#endif /* _DEMO_THREAD_H_INCLUDED_ */
#include "thread.h"
//互斥锁的创建
int thread_mutex_create(pthread_mutex_t *mtx)
{
int err;
pthread_mutexattr_t attr; //互斥锁属性变量
//1对互斥变量属性 pthread_mutexattr_t 初始化
err = pthread_mutexattr_init(&attr);
if (err != 0) {
fprintf(stderr, "pthread_mutexattr_init() failed, reason: %s\n",strerror(errno));
return ERROR;
}
//2设置互斥变量防 死锁检测 PTHREAD_MUTEX_ERRORCHECK 不允许同一个线程多次获取同一个锁导致的死锁
err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
if (err != 0) {
fprintf(stderr, "pthread_mutexattr_settype(PTHREAD_MUTEX_ERRORCHECK) failed, reason: %s\n",strerror(errno));
return ERROR;
}
//3对创建的互斥锁 mtx 设置 attr 属性
err = pthread_mutex_init(mtx, &attr);
if (err != 0) {
fprintf(stderr,"pthread_mutex_init() failed, reason: %s\n",strerror(errno));
return ERROR;
}
//3销毁互斥锁属性变量
err = pthread_mutexattr_destroy(&attr);
if (err != 0) {
fprintf(stderr,"pthread_mutexattr_destroy() failed, reason: %s\n",strerror(errno));
}
return OK;
}
//互斥锁的销毁
int thread_mutex_destroy(pthread_mutex_t *mtx)
{
int err;
err = pthread_mutex_destroy(mtx);
if (err != 0) {
fprintf(stderr,"pthread_mutex_destroy() failed, reason: %s\n",strerror(errno));
return ERROR;
}
return OK;
}
//互斥锁上锁
int thread_mutex_lock(pthread_mutex_t *mtx)
{
int err;
err = pthread_mutex_lock(mtx);
if (err == 0) {
return OK;
}
fprintf(stderr,"pthread_mutex_lock() failed, reason: %s\n",strerror(errno));
return ERROR;
}
//互斥锁解锁
int thread_mutex_unlock(pthread_mutex_t *mtx)
{
int err;
err = pthread_mutex_unlock(mtx);
#if 0
ngx_time_update();
#endif
if (err == 0) {
return OK;
}
fprintf(stderr,"pthread_mutex_unlock() failed, reason: %s\n",strerror(errno));
return ERROR;
}
#include "thread.h"
int thread_cond_create(pthread_cond_t *cond)
{
int err;
err = pthread_cond_init(cond, NULL);
if (err == 0) {
return OK;
}
fprintf(stderr, "pthread_cond_init() failed, reason: %s\n",strerror(errno));
return ERROR;
}
int thread_cond_destroy(pthread_cond_t *cond)
{
int err;
err = pthread_cond_destroy(cond);
if (err == 0) {
return OK;
}
fprintf(stderr, "pthread_cond_destroy() failed, reason: %s\n",strerror(errno));
return ERROR;
}
int thread_cond_signal(pthread_cond_t *cond)
{
int err;
err = pthread_cond_signal(cond);
if (err == 0) {
return OK;
}
fprintf(stderr, "pthread_cond_signal() failed, reason: %s\n",strerror(errno));
return ERROR;
}
int thread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mtx)
{
int err;
err = pthread_cond_wait(cond, mtx);
if (err == 0) {
return OK;
}
fprintf(stderr, "pthread_cond_wait() failed, reason: %s\n",strerror(errno));
return ERROR;
}
#ifndef _THREAD_POOL_H_INCLUDED_
#define _THREAD_POOL_H_INCLUDED_
#include "thread.h"
#define DEFAULT_THREADS_NUM 4 //默认线程池线程数量
#define DEFAULT_QUEUE_NUM 65535 //任务队列最大的数量
typedef unsigned long atomic_uint_t; //无符号整形
typedef struct thread_task_s thread_task_t; //任务
typedef struct thread_pool_s thread_pool_t; //线程池
//任务
struct thread_task_s {
thread_task_t *next; //下一个任务
uint_t id; //任务号
void *ctx; //上下文(任务函数的:参数)
void (*handler)(void *data); //任务函数
};
//控制 任务队列
typedef struct {
thread_task_t *first;
thread_task_t **last;
} thread_pool_queue_t;
//任务队列初始化宏替换
#define thread_pool_queue_init(q) \
(q)->first = NULL; \
(q)->last = &(q)->first
//线程池
struct thread_pool_s {
pthread_mutex_t mtx; //线程池的--互斥锁
thread_pool_queue_t queue; //线程池的--任务队列的控制
int_t waiting; //线程池的--任务队列的任务数
pthread_cond_t cond; //线程池的--条件变量
char *name; //线程池的名字
uint_t threads; //线程池的线程数量
int_t max_queue; //线程池任务队列最大长度
};
thread_task_t *thread_task_alloc(size_t size);
int_t thread_task_post(thread_pool_t *tp, thread_task_t *task);
thread_pool_t* thread_pool_init();
void thread_pool_destroy(thread_pool_t *tp);
#endif /* _THREAD_POOL_H_INCLUDED_ */
#include "thread_pool.h"
static void thread_pool_exit_handler(void *data);
//线程处理的函数
static void *thread_pool_cycle(void *data);
static int_t thread_pool_init_default(thread_pool_t *tpp, char *name);
static uint_t thread_pool_task_id; //任务队列的任务id
static int debug = 0;
thread_pool_t* thread_pool_init()
{
int err;
pthread_t tid; //线程的表示符
uint_t n;
pthread_attr_t attr; //线程的属性变量
//1创建线程池并分配内存
thread_pool_t *tp=NULL;
tp = calloc(1,sizeof(thread_pool_t));
if(tp == NULL){
fprintf(stderr, "thread_pool_init: calloc failed!\n");
return NULL;
}
//1线程池默认初始化
thread_pool_init_default(tp, NULL);
//2初始线程池的任务队列(宏函数替换):任务队列控制指针的初始化
thread_pool_queue_init(&tp->queue);
//3创建互斥锁
if (thread_mutex_create(&tp->mtx) != OK) {
free(tp);
return NULL;
}
//4创建条件变量
if (thread_cond_create(&tp->cond) != OK) {
(void) thread_mutex_destroy(&tp->mtx);
free(tp);
return NULL;
}
//5初始化线程的属性变量
err = pthread_attr_init(&attr);
if (err) {
fprintf(stderr, "pthread_attr_init() failed, reason: %s\n",strerror(errno));
free(tp);
return NULL;
}
//6设置线程池的线程的属性
//PTHREAD_CREATE_DETACHED创建时线程为分离状态(detached)
//主线程使用pthread_join无法等待结束的子线程
err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (err) {
fprintf(stderr, "pthread_attr_setdetachstate() failed, reason: %s\n",strerror(errno));
free(tp);
return NULL;
}
//7创建线程池里的处理线程
for (n = 0; n < tp->threads; n++) {
err = pthread_create(&tid, &attr, thread_pool_cycle, tp); //创建线程
if (err) {
fprintf(stderr, "pthread_create() failed, reason: %s\n",strerror(errno));
free(tp);
return NULL;
}
}
//8销毁线程属性变量
(void) pthread_attr_destroy(&attr);
return tp;
}
void thread_pool_destroy(thread_pool_t *tp)
{
uint_t n;
thread_task_t task;
volatile uint_t lock;
memset(&task,'\0', sizeof(thread_task_t));
//创建一个自杀线程任务
task.handler = thread_pool_exit_handler; //自杀任务的处理函数
task.ctx = (void *) &lock; //自杀任务的函数参数
//将自杀任务分配给每一个处理线程
for (n = 0; n < tp->threads; n++) {
lock = 1; //自杀函数的参数设置为1
if (thread_task_post(tp, &task) != OK) {
return;
}
//注意:如果该终止线程过程高消耗CPU,则把处理该过程的CPU让出,提高CPU利用率
while (lock) {
sched_yield(); //线程让出CPU使用权
}
//task.event.active = 0;
}
(void) thread_cond_destroy(&tp->cond); //销毁线程池里的 条件变量
(void) thread_mutex_destroy(&tp->mtx); //销毁线程池里的 互斥锁
free(tp); //销毁线程池
}
//终止该函数所在的线程
static void thread_pool_exit_handler(void *data)
{
uint_t *lock = data;
*lock = 0;
//销毁该线程
pthread_exit(0);
}
thread_task_t * thread_task_alloc(size_t size)
{
thread_task_t *task;
//分配1块thread_task_t+参数 的大小的内存
task = calloc(1,sizeof(thread_task_t) + size);
if (task == NULL) {
return NULL;
}
task->ctx = task + 1; //初始化任务的上下文(参数)
return task;
}
//将任务投递到线程池里
int_t thread_task_post(thread_pool_t *tp, thread_task_t *task)
{
if (thread_mutex_lock(&tp->mtx) != OK) { //线程池加锁
return ERROR;
}
//如果线程池等待的任务队列长度是否大于线程池任务队列最大长度
if (tp->waiting >= tp->max_queue) {
(void) thread_mutex_unlock(&tp->mtx); //线程池解锁
fprintf(stderr,"thread pool \"%s\" queue overflow: %ld tasks waiting\n",
tp->name, tp->waiting);
return ERROR;
}
//task->event.active = 1;
//初始化人物的id号 和 下一个任务的指针
task->id = thread_pool_task_id++;
task->next = NULL;
//给处理的线程发送条件变量
if (thread_cond_signal(&tp->cond) != OK) {
(void) thread_mutex_unlock(&tp->mtx);
return ERROR;
}
//任务队列控制指针last初始加入的任务
*tp->queue.last = task; //相当于 tp->queue.first=tast;
//初始化空的任务队列时last指针是指向first的
tp->queue.last = &task->next; //last指针指向task的下一个指针
tp->waiting++;
(void) thread_mutex_unlock(&tp->mtx);
if(debug)fprintf(stderr,"task #%lu added to thread pool \"%s\"\n",
task->id, tp->name);
return OK;
}
static void *thread_pool_cycle(void *data)
{
thread_pool_t *tp = data;
int err;
thread_task_t *task; //线程处理的任务
if(debug)fprintf(stderr,"thread in pool \"%s\" started\n", tp->name);
for ( ;; ) {
//-----------------线程池上锁 //上锁保护临界资源(任务队列)
if (thread_mutex_lock(&tp->mtx) != OK) {
return NULL;
}
tp->waiting--; //拿走任务队列1个任务,任务队列数量减1
while (tp->queue.first == NULL) { //如果线程池的任务队列为空
//******收到任务加入任务队列的条件变量*******
//!!!注意:只有当线程池解锁后&tp->mtx获取到锁后
// 才能执行线程任务
if (thread_cond_wait(&tp->cond, &tp->mtx)!= OK)
//*******************************************
{
//-------------------线程池解锁
(void) thread_mutex_unlock(&tp->mtx);
return NULL;
}
}
task = tp->queue.first; //取任务队列第一个任务
tp->queue.first = task->next; //把任务队列队头指针指向下一个任务
if (tp->queue.first == NULL) {
tp->queue.last = &tp->queue.first;
}
//-------------------线程池解锁
if (thread_mutex_unlock(&tp->mtx) != OK) {
return NULL;
}
if(debug) fprintf(stderr,"run task #%lu in thread pool \"%s\"\n",
task->id, tp->name);
//调用任务的处理函数
task->handler(task->ctx);
if(debug) fprintf(stderr,"complete task #%lu in thread pool \"%s\"\n",task->id, tp->name);
//任务的下个任务指针为NULL
task->next = NULL;
//处理完的任务释放资源 task里的void* ctx(参数)全部释放内存
free(task);
}
}
//线程池默认处理
static int_t thread_pool_init_default(thread_pool_t *tpp, char *name)
{
if(tpp)
{
tpp->threads = DEFAULT_THREADS_NUM; //设置线程池线程数量
tpp->max_queue = DEFAULT_QUEUE_NUM; //设置线程池任务队列最大长度
tpp->name = strdup(name?name:"default"); //设置线程池的名字
if(debug)fprintf(stderr,
"thread_pool_init, name: %s ,threads: %lu max_queue: %ld\n",
tpp->name, tpp->threads, tpp->max_queue);
return OK;
}
return ERROR;
}
#include "thread_pool.h"
//作为处理函数的参数 自定义结构体
struct test{
int arg1;
int arg2;
};
//处理函数1
void task_handler1(void* data){
static int index = 0;
printf("Hello, this is 1th test.index=%d\r\n", index++);
}
//处理函数2
void task_handler2(void* data){
static int index = 0;
printf("Hello, this is 2th test.index=%d\r\n", index++);
}
//处理函数3
void task_handler3(void* data){
static int index = 0;
struct test *t = (struct test *) data;
printf("Hello, this is 3th test.index=%d\r\n", index++);
printf("arg1: %d, arg2: %d\n", t->arg1, t->arg2);
}
int main(int argc, char **argv)
{
thread_pool_t* tp = NULL; //线程池
int i = 0;
//1初始化线程池
tp = thread_pool_init();
sleep(1);
//2创建任务
thread_task_t * test1 = thread_task_alloc(0); //参数0表示任务的处理函数参数大小为0
thread_task_t * test2 = thread_task_alloc(0); //参数0表示任务的处理函数参数大小为0
thread_task_t * test3 = thread_task_alloc(sizeof(struct test)); //参数表示任务的处理函数参数大小为sizeof(struct test)
//3设置任务的处理函数 和 处理函数所带的上下文(参数)
test1->handler = task_handler1;
test2->handler = task_handler2;
test3->handler = task_handler3;
((struct test*)test3->ctx)->arg1 = 555;
((struct test*)test3->ctx)->arg2 = 666;
//4将任务投递到线程池(线程池投递30个任务)
for(i=0;i<10;i++){
thread_task_post(tp, test1);
thread_task_post(tp, test2);
thread_task_post(tp, test3);
}
sleep(15); //等待线程处理任务
//5销毁线程池
// 线程里的线程会调用一个自杀任务来销毁自己的线程
thread_pool_destroy(tp);
}