thread_pool.h
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
typedef void *(*process)(void *arg);
typedef struct _thread_worker_t
{
process fun;
void *arg;
struct _thread_worker_t *next;
}thread_worker_t;
typedef struct _thread_pool_t
{
pthread_mutex_t mutex;
pthread_cond_t cond;
int shutdown;//是否销毁线程池
int thread_total;//初始化创建的线程个数
int queue_size;//请求线程的数量
pthread_t *thread_id;//线程ID数组
thread_worker_t *head;//用链表管理线程请求
}thread_pool_t;
int thread_pool_init(thread_pool_t **pool,int num);
int thread_pool_add_worker(thread_pool_t *pool,process fun,void *arg);
int thread_pool_destroy (thread_pool_t *pool);
#endif // THREAD_POOL_H
thread_pool.c
#include "thread_pool.h"
static void* thread_routine(void *arg)
{
//消费线程,从线程池中的head中获取头结点
thread_pool_t *pool = (thread_pool_t *)arg;
thread_worker_t *worker = NULL;
while(1)
{
pthread_mutex_lock(&(pool->mutex));
while(pool->queue_size == 0 && !pool->shutdown)
{
//池中还未有请求线程的 queue
//pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/
fprintf(stdout,"process[%lu] condtion wait...\n",pthread_self());
pthread_cond_wait(&(pool->cond),&(pool->mutex));
fprintf(stdout,"process[%lu] wake up...\n",pthread_self());
}
/*线程池要销毁了*/
if (pool->shutdown)
{
/*遇到break,continue,return等跳转语句,千万不要忘记先解锁*/
pthread_mutex_unlock (&(pool->mutex));
printf ("thread 0x%lu will exit\n", pthread_self ());
pthread_exit (NULL);
}
fprintf(stdout,"queue_size = %d\n",pool->queue_size);
//消费请求的线程
pool->queue_size--;
//将头节点移除出线程池链表中
worker = pool->head;
pool->head = worker->next;
pthread_mutex_unlock(&(pool->mutex));
//执行队列中的任务
(*worker->fun)(worker->arg);
free(worker);
worker = NULL;
}
return NULL;
}
int thread_pool_init(thread_pool_t **pool,int num)
{
if(num <= 0)
{
fprintf(stdout,"parameter error,[%s][%d]\n",__FILE__,__LINE__);
return -1;
}
thread_pool_t * tmp = NULL;
tmp = (thread_pool_t *)calloc(1,sizeof(thread_pool_t));
if(tmp == NULL)
{
fprintf(stdout,"calloc error,[%s][%d]\n",__FILE__,__LINE__);
return -1;
}
*pool = tmp;
pthread_mutex_init(&(tmp->mutex),NULL);
pthread_cond_init(&(tmp->cond),NULL);
tmp->queue_size = 0;//还未有请求线程队列
tmp->shutdown = 0;
tmp->thread_id = (pthread_t *)calloc(1,num*sizeof(pthread_t));
if(tmp->thread_id == NULL)
{
fprintf(stdout,"calloc error,[%s][%d]\n",__FILE__,__LINE__);
free(tmp);
tmp = NULL;
return -1;
}
pthread_attr_t attr;
//创建线程
int idx = 0;
int ret;
for(; idx < num; idx++)
{
ret = pthread_attr_init(&attr);
if(0 != ret)
{
return -1;
}
ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if(0 != ret)
{
return -1;
}
pthread_create(&(tmp->thread_id[idx]),&attr,thread_routine,tmp);
}
return 0;
}
int thread_pool_add_worker(thread_pool_t *pool,process fun,void *arg)
{
thread_worker_t *worker = NULL;
thread_worker_t *member = NULL;
worker = (thread_worker_t *)calloc(1,sizeof(thread_worker_t));
if(worker == NULL)
{
fprintf(stdout,"calloc error,[%s][%d]\n",__FILE__,__LINE__);
return -1;
}
worker->fun = fun;
worker->arg = arg;
worker->next = NULL;
//生产者,将节点插入到尾节点
pthread_mutex_lock(&(pool->mutex));
member = pool->head;
if(member != NULL)
{
//移到队尾
while(member->next != NULL)
{
member = member->next;
}
member->next = worker;
}
else
{
//头结点为空。说明队列中没有节点
pool->head = worker;
}
pool->queue_size++;
pthread_cond_signal(&(pool->cond));
pthread_mutex_unlock(&(pool->mutex));
return 0;
}
int thread_pool_destroy (thread_pool_t *pool)
{
if (pool->shutdown)
return -1;/*防止两次调用*/
pool->shutdown = 1;
/*唤醒所有等待线程,线程池要销毁了*/
pthread_cond_broadcast (&(pool->cond));
//分离线程,系统的资源自动释放
free (pool->thread_id);
/*销毁等待队列*/
thread_worker_t *worker = NULL;
while (pool->head != NULL)
{
worker = pool->head;
pool->head = worker->next;
free (worker);
}
/*条件变量和互斥量也别忘了销毁*/
pthread_mutex_destroy(&(pool->mutex));
pthread_cond_destroy(&(pool->cond));
free (pool);
/*销毁后指针置空是个好习惯*/
pool=NULL;
return 0;
}
main.c
#include "thread_pool.h"
#include <unistd.h>
#define MAX 10
void * myprocess(void *arg)
{
int *pdata = (int *)(arg);
fprintf(stdout,"process[%lu] process data = %d...,\n",pthread_self(),*pdata);
if(*pdata % 2 == 0)
{
do
{
fprintf(stdout,"process[%lu] process running\n",pthread_self());
sleep(10);
}while(0);
}
return 0;
}
int main(void)
{
thread_pool_t *pool;
thread_pool_init(&pool,10);
int array[MAX + 20];
int idx = 0;
for(;idx < 30 ;idx++)
{
array[idx] = idx;
thread_pool_add_worker(pool,myprocess,(void*)&array[idx]);
}
sleep(10);
thread_pool_destroy(pool);
pause();
return 0;
}
makefile:
.PHONY:clean all
CC=g++
CFLAGS=-Wall -g
BIN= main
all:$(BIN)
%.o:%.c
$(CC) $(CFLAGS) -c $< -o $@
main: thread_pool.o main.o
$(CC) $(CFLAGS) $^ -o $@ -lpthread
clean:
rm -f *.o $(BIN)
测试结果:
实现创建10个线程,这10个线程等到有任务加入,出于条件等待中,当客户讲任务加入到队列中时,线程争抢资源执行自己的回调函数。有些进程一直运行(if i % 2 == 0),故不能再去队列中消费任务,这等价于该线程未完成任务,
卡在(*worker->fun)(worker->arg),反之继续执行消费任务,最后观察发现有10个线程任然在运行,调用thread_pool_destroy向所有等待中的线程发送醒来信号,然后告诉所有线程退出。
pool的shutdown变量控制着整个线程的状态,没有这个将不能杀死这10个线程,注意while(pool->queue_size == 0 && !pool->shutdown)