参考 <https://blog.youkuaiyun.com/qq_36359022/article/details/78796784>
参考 <https://www.bilibili.com/video/BV1iJ411S7UA>
看了大概的思路,自己理解着敲一下,然后对比原来代码有些地方不同。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <time.h>
#define DEFAULT_TIME 1
typedef struct{
void* (*function)(void *);
void *arg;
}threadpoll_task_t;
typedef struct{
pthread_t thr_maneger;//管理线程
int thr_maneger_exit;//管理线程状态
pthread_mutex_t thr_mutex;//线程组
pthread_t *thr;//线程的锁
int thr_min_num;//最低
int thr_max_num;//最高
int thr_cap_num;//线程数
int thr_len_num;//线程活跃数
pthread_mutex_t task_mutex;//任务的锁
pthread_cond_t task_cond;//任务的条件变量
threadpoll_task_t *task_queue;//任务队列,环
int task_cap_num;//任务队列容量
int task_len_num;//任务队列的任务数
int task_head_index;//头
int task_tail_index;//尾
int task_suicide;//自杀式任务数
}threadpool_t;
void* threadpool_thread(void *arg){
threadpool_t *pool = (threadpool_t*)arg;
for(;;){
pthread_mutex_lock(&pool->task_mutex);
while(pool->task_len_num <=0 && pool->task_suicide <= 0)
pthread_cond_wait(&pool->task_cond,&pool->task_mutex);
//如果有自杀式任务,则自杀
if(pool->task_suicide > 0){
pool->task_suicide--;
pthread_mutex_unlock(&pool->task_mutex);
break;
}
//从任务队列中取数据
void* (*function)(void *);
void *arg;
function = pool->task_queue[pool->task_tail_index].function;
arg = pool->task_queue[pool->task_tail_index].arg;
pool->task_tail_index = (pool->task_tail_index+1) % pool->task_cap_num;
pool->task_len_num--;
pthread_mutex_unlock(&pool->task_mutex);
//活跃线程数+1
pthread_mutex_lock(&pool->thr_mutex);
pool->thr_len_num++;
pthread_mutex_unlock(&pool->thr_mutex);
function(arg);
//活跃线程数-1
pthread_mutex_lock(&pool->thr_mutex);
pool->thr_len_num--;
pthread_mutex_unlock(&pool->thr_mutex);
//唤醒可能阻塞中的task_add
pthread_cond_broadcast(&pool->task_cond);
}
pthread_exit(NULL);
}
int is_thread_alive(pthread_t tid){
int kill_rc = pthread_kill(tid,0);
if(kill_rc == ESRCH){
return 0;
}
return 1;
}
void *threadpoll_admin(void *arg){
threadpool_t *pool = (threadpool_t*)arg;
int thr_min_num;
int thr_max_num;
int thr_cap_num,new_thr_cap_num;
int thr_len_num;
int task_len_num;
int task_suicide;
int count,i;
pthread_mutex_lock(&pool->thr_mutex);
thr_min_num = pool->thr_min_num;
thr_max_num = pool->thr_max_num;
pthread_mutex_unlock(&pool->thr_mutex);
for(;;){
sleep(DEFAULT_TIME);
//判断管理线程是否需要退出
if(pool->thr_maneger_exit == 1){
break;
}
//取数据
pthread_mutex_lock(&pool->thr_mutex);
thr_cap_num = pool->thr_cap_num;
thr_len_num = pool->thr_len_num;
pthread_mutex_unlock(&pool->thr_mutex);
pthread_mutex_lock(&pool->task_mutex);
task_len_num = pool->task_len_num;
task_suicide = pool->task_suicide;
pthread_mutex_unlock(&pool->task_mutex);
printf("pool status "
",thr_cap_num=%d "
",thr_len_num=%d "
",task_len_num=%d "
",task_suicide=%d "
"\n",
thr_cap_num,thr_len_num,task_len_num,task_suicide);
//还没自杀完
if(task_suicide > 0){
continue;
}
//线程活跃数占80%,扩容
if(thr_len_num >= thr_cap_num * 0.8){//扩容
new_thr_cap_num = thr_cap_num*2;
if(new_thr_cap_num>thr_max_num){
new_thr_cap_num = thr_max_num;
}
count = new_thr_cap_num - thr_cap_num;
if(count <= 0)
continue;
pthread_mutex_lock(&pool->thr_mutex);
pool->thr_cap_num = new_thr_cap_num;
pthread_mutex_unlock(&pool->thr_mutex);
for(i=0;i<thr_max_num && count>0;i++){
//判断是否是自杀线程,回收
if(pool->thr[i] != 0 && !is_thread_alive(pool->thr[i])){
pthread_join(pool->thr[i],NULL);
pool->thr[i] = 0;
}
//创建线程
if(pool->thr[i] == 0){
pthread_create(&pool->thr[i],NULL,threadpool_thread,(void*)pool);
count--;
}
}
continue;
}
//线程活跃数占20%,缩容
if(thr_len_num <= thr_cap_num * 0.2){//缩容
new_thr_cap_num = thr_cap_num/2;
if(new_thr_cap_num<thr_min_num){
new_thr_cap_num = thr_min_num;
}
count = thr_cap_num - new_thr_cap_num;
if(count <= 0)
continue;
//缩容
pthread_mutex_lock(&pool->thr_mutex);
pool->thr_cap_num = new_thr_cap_num;
pthread_mutex_unlock(&pool->thr_mutex);
//自杀式任务数++++++
pthread_mutex_lock(&pool->task_mutex);
pool->task_suicide = count;
pthread_mutex_unlock(&pool->task_mutex);
//通知所有线程
pthread_cond_broadcast(&pool->task_cond);
continue;
}
}
//销毁所有线程
pthread_mutex_lock(&pool->thr_mutex);
thr_cap_num = pool->thr_cap_num;
thr_len_num = pool->thr_len_num;
pthread_mutex_unlock(&pool->thr_mutex);
pthread_mutex_lock(&pool->task_mutex);
pool->task_suicide = thr_cap_num;
pthread_mutex_unlock(&pool->task_mutex);
pthread_cond_broadcast(&pool->task_cond);
for(i=0;i<thr_max_num;i++){
if(pool->thr[i] != 0){
pthread_join(pool->thr[i],NULL);
pool->thr[i] = 0;
}
}
}
threadpool_t* threadpool_create(int thr_min_num,int thr_max_num,int task_cap_num){
threadpool_t *pool = malloc(sizeof(threadpool_t));
pthread_mutex_init(&pool->thr_mutex,NULL);
pool->thr = malloc(sizeof(pthread_t) * thr_max_num);
memset(pool->thr,0,sizeof(pthread_t) * thr_max_num);
pool->thr_min_num = thr_min_num;
pool->thr_max_num = thr_max_num;
pool->thr_cap_num = thr_min_num;
pool->thr_len_num = 0;
pthread_mutex_init(&pool->task_mutex,NULL);
pthread_cond_init(&pool->task_cond,NULL);
pool->task_queue = malloc(sizeof(threadpoll_task_t) * task_cap_num);
pool->task_cap_num = task_cap_num;
pool->task_len_num = 0;
pool->task_head_index = 0;
pool->task_tail_index = 0;
pool->task_suicide = 0;
//创建线程
int i;
for(i=0;i<pool->thr_cap_num;i++){
pthread_create(&pool->thr[i],NULL,threadpool_thread,(void*)pool);
}
//管理线程
pthread_create(&pool->thr_maneger,NULL,threadpoll_admin,(void*)pool);
return pool;
}
int threadpool_add_task(threadpool_t* pool,void* (*function)(void*),void* arg){
pthread_mutex_lock(&pool->task_mutex);
while(pool->task_len_num >= pool->task_cap_num)
pthread_cond_wait(&pool->task_cond,&pool->task_mutex);
//添加任务
pool->task_queue[pool->task_head_index].function = function;
pool->task_queue[pool->task_head_index].arg = arg;
pool->task_head_index = (pool->task_head_index+1) % pool->task_cap_num;
pool->task_len_num++;
pthread_mutex_unlock(&pool->task_mutex);
pthread_cond_signal(&pool->task_cond);
}
void threadpool_destroy(threadpool_t* pool){
pool->thr_maneger_exit = 1;
pthread_join(pool->thr_maneger,NULL);
pthread_mutex_lock(&pool->thr_mutex);
pthread_mutex_destroy(&pool->thr_mutex);
pthread_mutex_lock(&pool->task_mutex);
pthread_mutex_destroy(&pool->task_mutex);
pthread_cond_destroy(&pool->task_cond);
free(pool->thr);
free(pool->task_queue);
free(pool);
}
void* do_something(void*arg){
time_t t;
t = time(NULL);
printf("-- %lu,%s\n",pthread_self(),ctime(&t));
sleep(2 * DEFAULT_TIME);
t = time(NULL);
printf("!! %lu,%s\n",pthread_self(),ctime(&t));
}
int main(){
threadpool_t* pool = threadpool_create(20,100,200);
int i;
for(i=0;i<1000;i++){
threadpool_add_task(pool,do_something,NULL);
}
sleep(20 * DEFAULT_TIME);
for(i=0;i<50;i++){
threadpool_add_task(pool,do_something,NULL);
}
sleep(20 * DEFAULT_TIME);
for(i=0;i<1000;i++){
threadpool_add_task(pool,do_something,NULL);
}
threadpool_destroy(pool);
}