一、为什么要使用线程池?
1.降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
2.提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
3.提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
二、线程池的工作原理
三、nginx中使用线程池的场景举例
四、实现线程池的功能组件
1、执行(线程ID、终止标识、池管理组件对象);
2、任务(任务的回调函数、任务执行的参数);
3、池管理组件(互斥锁、条件变量、执行队列、任务队列);
五、线程池的具体代码实现
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#define KING_MAX_THREAD 10
#define KING_COUNTER_SIZE 100
typedef struct queue_job{
void (*job_function_hdl)(struct queue_job *job);
void *user_data;
struct queue_job *next;
struct queue_job *prev;
}nJob_t;
typedef struct thread_worker{
pthread_t tid;
int termainate;
struct thread_pool *pool;
struct thread_worker *next;
struct thread_worker *prev;
}nWorker_t;
typedef struct thread_pool{
nWorker_t *workers;
nJob_t *waiting_jobs;
pthread_mutex_t mutex;
pthread_cond_t cond;
}nThreadPool_t;
#define LL_ADD_HEAD(item, list) do{ \
item->prev = NULL; \
item->next = list; \
if(list != NULL) list->prev = item; \
list = item; \
}while(0)
#define LL_REMOVE_LIST(item, list) do{ \
if(item->prev != NULL) item->prev->next = item->next; \
if(item->next != NULL) item->next->prev = item->prev; \
if(item == list) list = list->next; \
item->prev = NULL; \
item->next = NULL; \
}while(0)
//消费者线程
void *nThreadWorkerHdl(void *arg){
nWorker_t *new_worker = (nWorker_t *)arg;
while(1){
pthread_mutex_lock(&new_worker->pool->mutex);
while(new_worker->pool->waiting_jobs == NULL){
//销毁线程池使用的
if(new_worker->termainate) break;
pthread_cond_wait(&new_worker->pool->cond, &new_worker->pool->mutex);
}
if(new_worker->termainate){
pthread_mutex_unlock(&new_worker->pool->mutex);
break;
}
nJob_t *job = new_worker->pool->waiting_jobs;
if(job != NULL){
LL_REMOVE_LIST(job, new_worker->pool->waiting_jobs);
}
pthread_mutex_unlock(&new_worker->pool->mutex);
if(job == NULL) continue;
job->job_function_hdl(job);
}
//if(new_worker){
//free(new_worker);
//}
pthread_exit(NULL);
}
int ntyMainThreadJoin(nThreadPool_t *pool){
if(pool == NULL) return -1;
nWorker_t *worker = pool->workers;
nWorker_t *ptr = NULL;
while(worker != NULL){
printf("回收子线程:%lu\n",worker->tid);
pthread_join(worker->tid, NULL);
ptr = worker->next;
free(worker);
worker = ptr;
}
return 0;
}
int ntyThreadPoolDestory(nThreadPool_t *pool) {
if(pool == NULL) return -1;
nWorker_t *worker = NULL;
for (worker = pool->workers; worker != NULL;worker = worker->next) {
worker->termainate = 1;
}
pthread_mutex_lock(&pool->mutex);
//这块的释放放在线程池销毁的函数中进行
//pool->workers = NULL;
pool->waiting_jobs = NULL;
pthread_cond_broadcast(&pool->cond);
pthread_mutex_unlock(&pool->mutex);
ntyMainThreadJoin(pool);
return 0;
}
//生产者线程,生产完消息后,通过条件变量唤醒阻塞在条件变量上的消费者线程
void nThreadPoolPushTask(nThreadPool_t *pool, nJob_t *new_job){
pthread_mutex_lock(&pool->mutex);
LL_ADD_HEAD(new_job, pool->waiting_jobs);
pthread_cond_broadcast(&pool->cond);
pthread_mutex_unlock(&pool->mutex);
return ;
}
int thread_pool_create(nThreadPool_t *pool, int thread_workers){
if(pool == NULL) return -1;
int idx = 0;
int ret;
if(thread_workers < 1) thread_workers = 1;
memset(pool, 0, sizeof(nThreadPool_t));
//pool->cond = PTHREAD_COND_INITIALIZER;
//pool->mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
memcpy(&pool->cond, &cond, sizeof(pthread_cond_t));
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
memcpy(&pool->mutex, &mutex, sizeof(pthread_mutex_t));
for(idx = 0; idx < thread_workers; idx++){
nWorker_t *new_worker = (nWorker_t*)malloc(sizeof(nWorker_t));
if(NULL == new_worker){
perror("malloc():");
return -1;
}
memset(new_worker, 0, sizeof(nWorker_t));
new_worker->pool = pool;
ret = pthread_create(&new_worker->tid, NULL, nThreadWorkerHdl, (void *)new_worker);
if(ret < 0){
perror("phtread_create():");
free(new_worker);
return idx;
}
//设置线程分离,不需要父进程回收
//pthread_detach(new_worker->tid);
LL_ADD_HEAD(new_worker, new_worker->pool->workers);
}
//返回创建成功的线程个数
return idx;
}
void king_counter_hdl(nJob_t *job){
int index = *(int*)job->user_data;
printf("index : %d, selfid : %lu\n", index, pthread_self());
free(job->user_data);
free(job);
}
int main(int argc, char *argv[]){
nThreadPool_t pool;
int i;
//这个是创建的多个消费者线程,形成线程池,消费处理任务
memset(&pool, 0, sizeof(nThreadPool_t));
thread_pool_create(&pool, KING_MAX_THREAD);
//这个是主控线程,作为生产者生产消息
for(i = 0; i < KING_COUNTER_SIZE; i++){
nJob_t *new_job = (nJob_t *)malloc(sizeof(nJob_t));
if(new_job == NULL){
perror("malloc():");
return -1;
}
new_job->job_function_hdl = king_counter_hdl;
new_job->user_data = (int *)malloc(sizeof(int));
*(int *)new_job->user_data = i;
nThreadPoolPushTask(&pool, new_job);
}
//睡眠十秒钟等待任务队列被执行完成
sleep(10);
printf("睡眠十秒钟等待任务队列被执行完成\n");
//线程池销毁
ntyThreadPoolDestory(&pool);
return 0;
}
代码调试执行:
[root@localhost c++_test]# gcc my_pthread_pool.c -o test -lpthread
[root@localhost c++_test]# ./test
index : 99, selfid : 140216515962624
index : 96, selfid : 140216515962624
index : 95, selfid : 140216515962624
index : 94, selfid : 140216515962624
index : 93, selfid : 140216515962624
index : 92, selfid : 140216515962624
index : 91, selfid : 140216515962624
index : 90, selfid : 140216515962624
index : 89, selfid : 140216515962624
index : 88, selfid : 140216515962624
index : 87, selfid : 140216515962624
index : 86, selfid : 140216515962624
index : 85, selfid : 140216515962624
index : 84, selfid : 140216515962624
index : 83, selfid : 140216515962624
index : 82, selfid : 140216515962624
index : 81, selfid : 140216515962624
index : 80, selfid : 140216515962624
index : 79, selfid : 140216515962624
index : 78, selfid : 140216515962624
index : 77, selfid : 140216515962624
index : 76, selfid : 140216515962624
index : 75, selfid : 140216515962624
index : 74, selfid : 140216515962624
index : 73, selfid : 140216515962624
index : 72, selfid : 140216515962624
index : 71, selfid : 140216515962624
index : 70, selfid : 140216515962624
index : 69, selfid : 140216515962624
index : 68, selfid : 140216515962624
index : 67, selfid : 140216515962624
index : 66, selfid : 140216515962624
index : 65, selfid : 140216515962624
index : 64, selfid : 140216515962624
index : 63, selfid : 140216515962624
index : 97, selfid : 140216499177216
index : 61, selfid : 140216499177216
index : 60, selfid : 140216499177216
index : 62, selfid : 140216515962624
index : 58, selfid : 140216490784512
index : 56, selfid : 140216490784512
index : 55, selfid : 140216490784512
index : 54, selfid : 140216490784512
index : 98, selfid : 140216507569920
index : 53, selfid : 140216490784512
index : 52, selfid : 140216490784512
index : 50, selfid : 140216490784512
index : 49, selfid : 140216490784512
index : 48, selfid : 140216490784512
index : 47, selfid : 140216490784512
index : 46, selfid : 140216490784512
index : 45, selfid : 140216490784512
index : 59, selfid : 140216499177216
index : 43, selfid : 140216482391808
index : 51, selfid : 140216507569920
index : 39, selfid : 140216507569920
index : 38, selfid : 140216507569920
index : 37, selfid : 140216507569920
index : 36, selfid : 140216507569920
index : 35, selfid : 140216507569920
index : 34, selfid : 140216507569920
index : 33, selfid : 140216507569920
index : 32, selfid : 140216507569920
index : 31, selfid : 140216507569920
index : 30, selfid : 140216507569920
index : 29, selfid : 140216507569920
index : 28, selfid : 140216482391808
index : 26, selfid : 140216465606400
index : 24, selfid : 140216465606400
index : 23, selfid : 140216465606400
index : 22, selfid : 140216465606400
index : 21, selfid : 140216465606400
index : 20, selfid : 140216465606400
index : 19, selfid : 140216465606400
index : 18, selfid : 140216465606400
index : 17, selfid : 140216465606400
index : 16, selfid : 140216465606400
index : 57, selfid : 140216515962624
index : 27, selfid : 140216507569920
index : 12, selfid : 140216507569920
index : 11, selfid : 140216507569920
index : 10, selfid : 140216507569920
index : 9, selfid : 140216507569920
index : 8, selfid : 140216507569920
index : 7, selfid : 140216507569920
index : 6, selfid : 140216507569920
index : 5, selfid : 140216507569920
index : 4, selfid : 140216507569920
index : 3, selfid : 140216507569920
index : 2, selfid : 140216507569920
index : 1, selfid : 140216507569920
index : 0, selfid : 140216507569920
index : 42, selfid : 140216473999104
index : 40, selfid : 140216457213696
index : 25, selfid : 140216482391808
index : 44, selfid : 140216490784512
index : 15, selfid : 140216448820992
index : 14, selfid : 140216465606400
index : 13, selfid : 140216515962624
index : 41, selfid : 140216499177216
睡眠十秒钟等待任务队列被执行完成
回收子线程:140216440428288
回收子线程:140216448820992
回收子线程:140216457213696
回收子线程:140216465606400
回收子线程:140216473999104
回收子线程:140216482391808
回收子线程:140216490784512
回收子线程:140216499177216
回收子线程:140216507569920
回收子线程:140216515962624
以上就是我对线程池的理解实现,有什么不明白之处请在评论区留言,我们一起讨论学习。