线程池概念和使用
概念:
通俗的讲就是一个线程的池子,可以循环的完成任务的一组线程集合
必要性:
我们平时创建一个线程,完成某一个任务,等待线程的退出。但当需要创建大量的线程时,假设T1为创建线程时间,T2为在线程任务执行时间,T3为线程销毁时间,当 T1+T3 > T2,这时候就不划算了,使用线程池可以降低频繁创建和销毁线程所带来的开销,任务处理时间比较短的时候这个好处非常显著。
线程池的基本结构:
1 任务节点,存储需要处理的任务,由工作线程来处理这些任务
2 线程池工作线程,它是任务队列任务的消费者,等待新任务的信号
代码实例:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
//线程池大小
#define POOL_NUM 10
//存放任务的结构体
typedef struct Task{
void *(*func)(void *arg);
void *arg;
struct Task *next;
}Task;
//定义线程池的结构体
//每个任务是一个单独的节点,线程池为这个队列
//每当一个任务节点创建好时,他就会被存放到线程池的尾部
// 然后busywork++;
typedef struct ThreadPool{
pthread_mutex_t taskLock;
pthread_cond_t newTask;
pthread_t tid[POOL_NUM];
Task *queue_head;
int busywork;//在线城池里的线程个数
}ThreadPool;
ThreadPool *pool;
//使线程池中的线程开始工作
//需要接收到线程池中有任务的信号才可以去让线程工作
void *workThread(void *arg){
while(1){
pthread_mutex_lock(&pool->taskLock);
pthread_cond_wait(&pool->newTask,&pool->taskLock);
// 需要等待线程分配好任务后在运行
Task *ptask = pool->queue_head;//收到信号后将即将运行的节点从线程池中移除
pool->queue_head = pool->queue_head->next;
pthread_mutex_unlock(&pool->taskLock);
ptask->func(ptask->arg);//运行,让线程去执行他真正需要执行的操作
pool->busywork--;//线程池中线程减少
}
}
//真正的工作
void *realwork(void *arg){
printf("Finish work %d\n",(int)arg);
}
//将任务添加到线程池中
//以队列的方式,先进先出,先来的先运行
void pool_add_task(int arg){
Task *newTask;
//判断线程池是否已满
//满了就等一会之后看有没有运行完的线程
pthread_mutex_lock(&pool->taskLock);
while(pool->busywork>=POOL_NUM){
pthread_mutex_unlock(&pool->taskLock);
usleep(10000);
pthread_mutex_lock(&pool->taskLock);
}
pthread_mutex_unlock(&pool->taskLock);
//新建任务
newTask = malloc(sizeof(Task));
newTask->func = realwork;
newTask->arg = arg;
//将新建的任务添加到线程池中
//只是添加线程,线程是否运行完毕未知
pthread_mutex_lock(&pool->taskLock);
Task *member = pool->queue_head;
if(member==NULL){
pool->queue_head = newTask;
}else{
while(member->next!=NULL){
member=member->next;
}
member->next = newTask;
}
pool->busywork++;
//任务已经被分配他需要运行的函数,可以发出信号让线程池中的任务运行
pthread_cond_signal(&pool->newTask);
pthread_mutex_unlock(&pool->taskLock);
}
//线程池的初始化
void pool_init(){
pool = malloc(sizeof(ThreadPool));
//两种锁的动态初始化
pthread_mutex_init(&pool->taskLock,NULL);
pthread_cond_init(&pool->newTask,NULL);
pool->queue_head = NULL;
pool->busywork=0;
//创建i个线程,每个线程可以认为是一个任务,并使他们准备工作
for(int i=0;i<POOL_NUM;i++){
pthread_create(&pool->tid[i],NULL,workThread,NULL);
}
}
//线程池的销毁
void pool_destory(){
Task *head;
while(pool->queue_head!=NULL){
head = pool->queue_head;
pool->queue_head = pool->queue_head->next;
free(head);
}
pthread_mutex_destroy(&pool->taskLock);
pthread_cond_destroy(&pool->newTask);
free(pool);
}
int main(){
pool_init();
sleep(20);
for(int i=1;i<=20;i++){
pool_add_task(i);
}
sleep(5);
pool_destory();
}