线程池听名字很好理解,就是把多个线程放在一个池里面,然后做相应的操作。在线程池中 我们会再开始的时候创建一个最小线程数,然后往线程池里面添加或者销毁线程我们通过一个主导线程进行管理。对线程公共的资源我们引入了互斥锁进行制约,当线程池里面的任何一个线程访问该资源的时候都要进行加锁解锁操作,这样能有效的使得每个线程正确的获得该资源不会发生混乱。还有每个线程要做的任务,这里我们有一个任务队列配合着线程,有任务就交给空闲的线程进行处理。如果不引入线程池,而是来一个任务就创建一个线程的话这样的效率是很低的,CPU的资源都浪费在了创建和销毁线程身上,我们建立若干个线程统一进行管理这样就会使CPU更加高效的运行。
参考代码:
/*************************************************************************
> File Name: thread_poll.cpp
> Author: chencj
> Mail: 1378755306@qq.com
> Created Time: 2020年08月12日 星期三 17时53分06秒
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#define DEFAULT_TIME 10 //管理者线程10秒检测一次
#define MIN_WAIT_TASK_NUM 10 //如果任务队列的size大于这个,就添加新的线程到线程池中
#define DEFAULT_THREAD_VARY 10 //每次添加的或者删除的线程数量
/*任务队列的类型*/
typedef struct {
void *(*Function)(void *); //类型为void *类型的函数指针,用作任务的回调函数
void *arg; //回调函数的参数
}threadpool_task;
/*描述线程池中的相关信息*/
struct threadpool_t{
pthread_mutex_t Lock; //用于锁住本结构体
pthread_mutex_t thread_counter; //记录忙线程个数的锁---为basy_thr_num 服务
pthread_cond_t queue_not_full; //当任务队列满的时,添加新的任务会阻塞,等待此条件变量
pthread_cond_t queue_not_empty; //当任务队列不为空,通知等待任务的线程
pthread_t *threads; //线程数组
pthread_t adjust_tid; //管理者线程
threadpool_task *task_queue; //任务队列
int min_thr_num; //线程池中最小的线程数
int max_thr_num; //线程池中最大的线程数
int live_thr_num; //线程池中存活的线程数
int busy_thr_num; //线程池中执行任务的线程数
int wait_exit_thr_num; //线程池中待销毁的线程数
int queue_front; //任务队头
int queue_rear; //任务队尾
int queue_size; //实际任务数
int queue_max_size; //最多可执行的任务数
int shutdown; //标志线程池的消亡 true->dead false->alive
};
void *threadpool_thread(void *);
void *adjust_thread(void *);
int is_thread_alive(pthread_t );
int threadpool_free(threadpool_t *);
threadpool_t *threadpool_create(int min_thr_num,int max_thr_num,int queue_max_size)
{
int i;
threadpool_t *pool = NULL;
do{
if((pool = (threadpool_t *)malloc(sizeof(threadpool_t))) == NULL){
printf("malloc threadpool fail\n");
break;
}
pool->min_thr_num = min_thr_num;
pool->max_thr_num = max_thr_num;
pool->busy_thr_num = 0;
pool->live_thr_num = min_thr_num;
pool->busy_thr_num = 0;
pool->queue_front = 0;
pool->queue_max_size = queue_max_size;
pool->queue_rear = 0;
pool->queue_size = 0;
//线程池中的线程开辟空间
pool->threads = (pthread_t *)malloc(sizeof(pthread_t)*max_thr_num);
if(pool->threads == NULL){
printf("threads malloc fail\n");
break;
}
memset(pool->threads,0,sizeof(pthread_t)*max_thr_num);
//任务队列开辟空间
pool->task_queue = (threadpool_task *)malloc(sizeof(threadpool_task)*queue_max_size);
if(pool->task_queue == NULL){
printf("task_queue malloc fail\n");
break;
}
/*初始化锁以及条件变量*/
if(pthread_mutex_init(&pool->Lock,NULL) != 0
||pthread_mutex_init(&pool->thread_counter,NULL) != 0
||pthread_cond_init(&pool->queue_not_empty,NULL) != 0
||pthread_cond_init(&pool->queue_not_full,NULL) != 0)
{
printf("init the lock or cond fail\n");
break;
}
/*启动min_thr_num 个work thread 此时线程都没有任务*/
for(i = 0;i < min_thr_num; i++)
{
pthread_create(&(pool->threads[i]),NULL,threadpool_thread,(void *)pool); //pool指向当前线程池
printf("start thread 0x%x...\n",(unsigned int)pool->threads[i]);
}
//启动管理者线程
pthread_create(&pool->adjust_tid,NULL,adjust_thread,(void *)pool);
return pool;
}while(0);
threadpool_free(pool); //前面都调用失败 释放pool存储的空间
return NULL;
}
/*向线程池中添加任务*/
int threadpool_add(threadpool_t *pool,void *(*Function)(void *arg),void *arg)
{
pthread_mutex_lock(&(pool->Lock));
/*队列已满,wait阻塞*/
while((pool->queue_size == pool->queue_max_size) && (!pool->shutdown)) {
pthread_cond_wait(&(pool->queue_not_full),&(pool->Lock));
}
if(pool->shutdown)
{
pthread_mutex_unlock(&(pool->Lock));
}
//清队尾
if(pool->task_queue[pool->queue_rear].arg != NULL) {
free(pool->task_queue[pool->queue_rear].arg);
pool->task_queue[pool->queue_rear].arg = NULL;
}
/*添加任务到队列里面*/
pool->task_queue[pool->queue_rear].Function = Function;
pool->task_queue[pool->queue_rear].arg = arg;
pool->queue_rear = (pool->queue_rear + 1) % pool->queue_max_size;
pool->queue_size++;
/*添加完任务,唤醒线程池中等待处理任务的线程*/
pthread_cond_signal(&(pool->queue_not_empty));
pthread_mutex_unlock(&(pool->Lock));
return 0;
}
/*线程池中各个工作现线程*/
void *threadpool_thread(void *threadpool)
{
threadpool_t *pool = (threadpool_t *)threadpool;
threadpool_task task;
while(1)
{
/*刚创建出线程,等待队列里面有任务,否则阻塞等待,直到任务队列中有任务在唤醒*/
pthread_mutex_lock(&(pool->Lock)); //加锁
//queue_size == 0说明没有任务,调wait阻塞在条件变量上
//pthread_cond_wait先对信号量自动解锁,有信号传过来不阻塞之后在自动加锁
while((pool->queue_size == 0) && (!pool->shutdown)) {
printf("thread 0x%x is waiting\n",(unsigned int)pthread_self());
//有任务队列不为空的信号传来会不阻塞
pthread_cond_wait(&(pool->queue_not_empty),&(pool->Lock));
/*清除指定数目的空闲线程*/
if(pool->wait_exit_thr_num > 0) {
pool->wait_exit_thr_num--;
/*如果线程池中存活的线程大于最小值时可以结束当前线程*/
if(pool->live_thr_num > pool->min_thr_num)
{
printf("thread 0x%x is exiting\n",(unsigned int)pthread_self());
pool->live_thr_num--;
pthread_mutex_unlock(&(pool->Lock));
pthread_exit(NULL);
}
}
}
/*如果指定关闭线程池*/
if(pool->shutdown)
{
pthread_mutex_unlock(&(pool->Lock));
printf("thread 0x%x is exiting\n",(unsigned int)pthread_self());
pthread_exit(NULL);
}
/*从任务队列里面获取任务*/
task.Function = pool->task_queue[pool->queue_front].Function;
task.arg = pool->task_queue[pool->queue_front].arg;
pool->queue_front = (pool->queue_front + 1) % pool->queue_max_size;//出队
pool->queue_size--; //任务数减一
/*通知有新的任务可以进来*/
pthread_cond_broadcast(&(pool->queue_not_full));
pthread_mutex_unlock(&(pool->Lock));
//执行任务
printf("thread 0x%x start working\n",(unsigned int)pthread_self());
pthread_mutex_lock(&(pool->thread_counter)); //忙线程数加1
pool->busy_thr_num++;
pthread_mutex_unlock(&(pool->thread_counter));
(*(task.Function))(task.arg); //执行回调函数
/*任务结束处理*/
printf("thread 0x%x end working\n",(unsigned int)pthread_self());
pthread_mutex_lock(&(pool->thread_counter));
pool->busy_thr_num--; //忙线程数减一
pthread_mutex_unlock(&(pool->thread_counter));
}
pthread_exit(NULL); //线程退出
}
/*主导线程*/
void *adjust_thread(void *threadpool)
{
int i;
threadpool_t *pool = (threadpool_t *)threadpool;
while(!pool->shutdown) {
sleep(DEFAULT_TIME); //定时对线程进行管理
pthread_mutex_lock(&(pool->Lock));
int queue_size = pool->queue_size;
int live_thr_num = pool->live_thr_num;
pthread_mutex_unlock(&(pool->Lock));
pthread_mutex_lock(&(pool->thread_counter));
int busy_thr_num = pool->busy_thr_num;
pthread_mutex_unlock(&(pool->thread_counter));
//创建新线程算法
if(queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num) {
pthread_mutex_lock(&(pool->Lock));
int add = 0;
for(i = 0; i< pool->max_thr_num && add < DEFAULT_THREAD_VARY
&& pool->live_thr_num < pool->max_thr_num; i++)
{
if(pool->threads[i] == 0 || !is_thread_alive(pool->threads[i])) {
pthread_create(&(pool->threads[i]),NULL,threadpool_thread,(void *)pool);
add++;
pool->live_thr_num++;
}
}
pthread_mutex_unlock(&(pool->Lock));
}
//销毁多余线程算法
if((busy_thr_num * 2) < live_thr_num && live_thr_num > pool->min_thr_num) {
pthread_mutex_lock(&(pool->Lock));
pool->wait_exit_thr_num = DEFAULT_THREAD_VARY;
pthread_mutex_unlock(&(pool->Lock));
for(i = 0;i < DEFAULT_THREAD_VARY; i++) {
//通知空闲的线程 他们会自动终止
pthread_cond_signal(&(pool->queue_not_empty));
}
}
}
return NULL;
}
int threadpool_destory(threadpool_t *pool)
{
int i;
if(pool == NULL)
return -1;
pool->shutdown = true;
/*先销毁管理线程*/
pthread_join(pool->adjust_tid,NULL);
//通知所有空闲线程
for(i = 0;i < pool->live_thr_num; i++)
pthread_cond_broadcast(&(pool->queue_not_empty));
for(i = 0;i < pool->live_thr_num; i++)
pthread_join(pool->threads[i],NULL);
threadpool_free(pool);
return 0;
}
int threadpool_free(threadpool_t *pool)
{
if(pool == NULL)
return -1;
if(pool->task_queue)
free(pool->task_queue);
if(pool->threads)
{
free(pool->threads);
pthread_mutex_lock(&(pool->Lock));
pthread_mutex_destroy(&(pool->Lock));
pthread_mutex_lock(&(pool->thread_counter));
pthread_mutex_destroy(&(pool->thread_counter));
pthread_cond_destroy(&(pool->queue_not_full));
pthread_cond_destroy(&(pool->queue_not_empty));
}
free(pool);
pool = NULL;
return 0;
}
/*发0信号,测试线程是否存活*/
int is_thread_alive(pthread_t tid)
{
int kill_rc = pthread_kill(tid,0);
if(kill_rc == ESRCH)
return 0;
return 1;
}
void *process(void *arg)
{
printf("thread 0x%x working on task %d\n",(unsigned int)pthread_self(),*(int *)arg);
sleep(1);
printf("task %d is end\n",*(int *)arg);
return NULL;
}
int main()
{
threadpool_t *thp = threadpool_create(3,100,100); //创建线程池,池中最小线程数,最大线程数,队列最大线程数
printf("pool inited\n");
int num[21], i;
for(i = 1;i <= 20; i++)
{
num[i] = i;
printf("add task %d\n",i);
threadpool_add(thp,process,(void *)&num[i]); //向线程池中添加任务
}
sleep(10); //等待子线程完成任务
threadpool_destory(thp); //销毁线程池
return 0;
}