Linux系统编程(十)线程池

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>
#include <errno.h>

#define DEFAULT_TIME 10
#define DEFAULT_THREAD_VARY 10
#define MIN_WAIT_TASK_NUM 10

typedef struct threadpool_task { void *(*function)(void *); void *arg; } threadpool_task_t; typedef struct threadpool { pthread_mutex_t lock; // 锁住本结构体 pthread_mutex_t thread_counter; // 记录忙状态线程个数的锁 pthread_cond_t queue_not_full; // 任务队列满时,添加任务的线程阻塞,等待此条件变量 pthread_cond_t queue_not_empty; // 任务队列不为空,通知等待任务的线程 pthread_t *threads; // 存放线程池中的线程号tid pthread_t adjust_tid; // 存管理线程tid threadpool_task_t *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; // task_queue队头下标 int queue_rear; // task_queue队尾下标 int queue_size; // task_queue队中实际任务数 int queue_max_size; // task_queue队列可容纳任务数量上限 int shutdown; // 线程池使用状态 } threadpool_t; int is_thread_alive(pthread_t tid) { int kill_rc = pthread_kill(tid, 0); if(kill_rc == ESRCH) return 0; else return -1; } 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_empty)); pthread_cond_destroy(&(pool->queue_not_full)); } free(pool); pool = NULL; return 0; } int threadpool_destory(threadpool_t *pool) { int i; if(pool == NULL) return -1; pool->shutdown = 1; 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; } void *threadpool_thread(void *threadpool) { threadpool_t *pool = (threadpool_t *)threadpool; threadpool_task_t task; while(1) { pthread_mutex_lock(&(pool->lock)); while((pool->queue_size == 0) && (!pool->shutdown)){ printf("thread 0x%lx is waiting\n", 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%lx is exsiting\n", 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%lx is existing\n", pthread_self()); pthread_detach(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%lx start working\n", pthread_self()); (*(task.function))(task.arg); printf("thread 0x%lx end working\n", 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) { threadpool_t *pool = (threadpool_t *)threadpool; int i; 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; } 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"); 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->queue_size = 0; pool->queue_max_size = queue_max_size; pool->queue_front = 0; pool->queue_rear = 0; pool->shutdown = 0; pool->threads = (pthread_t *)malloc(sizeof(pthread_t)*max_thr_num); if(pool->threads == NULL) { printf("malloc threads fail\n"); break; } memset(pool->threads, 0, sizeof(pthread_t)*max_thr_num); pool->task_queue = (threadpool_task_t*)malloc(sizeof(threadpool_task_t)*queue_max_size); if(pool->task_queue == NULL) { printf("mallc task_queue 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 mutex or cond fail\n"); break; } for(i = 0; i < min_thr_num; i++) { pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void*)pool); printf("start thread 0x%lx...\n", pool->threads[i]); } pthread_create(&(pool->adjust_tid), NULL, adjust_thread, (void*)pool); return pool; }while(0); threadpool_free(pool); return NULL; } void threadpool_add(threadpool_t *pool, void *(*func)(void*arg), void *arg) { pthread_mutex_lock(&(pool->lock)); // fang zhi qiang suo while((pool->queue_size == pool->queue_max_size) && (!pool->shutdown)) pthread_cond_wait(&(pool->queue_not_full), &(pool->lock)); if(pool->shutdown){ pthread_cond_broadcast(&(pool->queue_not_empty)); pthread_mutex_unlock(&(pool->lock)); } if(pool->task_queue[pool->queue_rear].arg != NULL) pool->task_queue[pool->queue_rear].arg = NULL; pool->task_queue[pool->queue_rear].function = func; 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)); } void *process(void *arg) { printf("thread 0x%lx working on task %p\n", pthread_self(), arg); sleep(1); printf("task %p is end\n", arg); return NULL; } int main(int argc, char** argv) { threadpool_t *thp = threadpool_create(3, 100, 100); int num[20]; for(int i = 0; i < 20; i++) { num[i] = i; threadpool_add(thp, process, (void*)&num[i]); } sleep(10); threadpool_destory(thp); return 0; }

 

posted @ 2022-05-18 09:35  青山渺渺  阅读(127)  评论(0编辑  收藏  举报