线程池
如果一个客户端建立连接使用创建一个线程用于处理这一个线程, 处理结束的时候把这一个线程删除, 这个时候会导致线程的创建以及销毁会消耗大量的时间
这时候可以一次性创建多个线程, 这几个线程统称线程池, 如果客户端建立一个连接, 线程池分配一个线程处理客户发过来的数据, 不处理的时候这几个线程阻塞
可以使用条件变量进行阻塞
线程的数量可以随着连接的个数, 时间等条件进行变换, 但是要有一个上限, 连接分个数增加的时候加线程, 如果忙的线程数量比较少的时候释放线程, 这一些处理使用一个adjust线程进行处理
实际实现
主函数
- 创建一个线程池
- 在里面添加任务
- 等待
- 关闭线程池
线程池
-
初始化各种数据
-
获取基础线程, 让他们阻塞等待任务
-
获取任务, 唤醒线程处理
-
处理结束接着阻塞
后台的控制线程(adjust_thread)根据线程的实际使用情况添加或者释放线程
/*************************************************************************
> File Name: thread_pool.c
> Author: XvSenfeng
> Mail: 1458612070@qq.com
> Created Time: Wed 10 Apr 2024 08:23:27 PM CST
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
使用的头文件
//多长时间判断一下是否需要增加获取减少线程个数
//这一个值小一点看现象
#define DEFAULT_TIME 3
//最小的执行的线程的个数
#define MIN_WAIT_TASK_NUM 10
//增加减少的时候步长
#define DEFAULT_THREAD_VARY 10
#define true 1
#define false 0
使用的宏定义
//记录一个回调函数, 由于线程执行
typedef struct {
void *(*function)(void *);
void *arg;
} threadpool_task_t;
//线程池的控制结构体
typedef struct{
pthread_mutex_t lock; //这一个结构体使用
pthread_mutex_t thread_counter; //记录忙状态的线程的个数
pthread_cond_t queue_not_full; //队列,没有满的时候添加使用
pthread_cond_t queue_not_empty;
pthread_t *threads; //线程数组, 记录现在使用的线程的pid
pthread_t adjust_tid; //管理者的id
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;
int queue_rear;
int queue_size;
int queue_max_size;
int shutdown; //记录这一个线程池有没有使用
}threadpool_t;
线程池的控制结构体, 以及任务信息记录的结构体
void *adjust_thread(void *threadpool);
void threadpool_free(threadpool_t *pool);
//普通的线程处理函数
void *threadpool_thread(void *threadpool){
threadpool_t *pool = (threadpool_t *)threadpool;
threadpool_task_t task;
while(true){
pthread_mutex_lock(&(pool->lock));
//判断一下现在没有可以执行的任务, 并且这一个线程组还没有销毁
while((pool->queue_size == 0) && (!pool->shutdown)){
printf("thread %#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 %#x is exiting\n", (unsigned int)pthread_self());
pool->live_thr_num--;
pthread_mutex_unlock(&pool->lock);
pthread_exit(NULL);
}
}
}
//这时候是有待处理的任务, 或者这一个线程池被销毁了