一.功能
线程池中有若干个线程,用于执行大量相对短暂的任务
二.功能描述
计算密集型任务:线程池中线程个数=CPU个数
I/O密集型任务:线程池中线程个数>CPU个数
当任务增加时,可以动态增加线程池中线程个数,当任务执行完成后,可以动态减少线程池中线程个数
运用生产消费者模型,生产者线程向任务队列中添加任务,任务队列中如果没有任务,如果有等待线程就唤醒并执行任务,如果线程池中没有等待线程并且没有达到上限,就添加新的线程到线程池
三.代码梳理
main.c
创建线程池 -->初始化线程池-->不断向线程池中添加任务-->销毁线程池
线程池的结构
// 任务队列(链表)
typedef struct task{
void *(*pfun)(void*); // 回调函数
void *arg; // 回调函数参数
struct task *next;
}task_t;
//互斥量
typedef struct condition {
pthread_mutex_t mutex;
pthread_cond_t pcond;
} condition_t;
typedef struct threadpool {
condition_t cond; // 同步互斥
task_t *first; // 任务队列的对头
task_t *tail; // 队尾指针
int max_thread; // 最大线程个数
int idle; // 空闲线程个数
int counter; // 线程池当前的线程个数
}threadpool_t;
threadpool.h所做的工作
1)初始化线程池
2)执行线程池中的任务(创建线程时传参传线程池的结构体)
a)上锁
b)空闲线程个数+1 ?
c)如果此时任务队列为空,等待添加任务
d)因为此时线程将要执行任务,所以空闲线程-1
e)如果此时任务队列不为空
1>取此时任务队列的队头
2>防止任务执行太久,解锁
3>执行任务
4>上锁,释放原来的队头,解锁
3)向线程池中添加任务
a)生成任务结点 task_t
b)上锁(对链表进行的动作都要上锁)
c)判断队头是否为空,采用尾插,更新尾巴
d)如果有空闲线程,发送signal,或者线程个数小于最大线程个数,增加线程。
e)解锁
4)销毁线程池
销毁互斥量和条件变量
上代码:
1 #include <unistd.h>
2 #include <pthread.h>
3 #include <stdlib.h>
4 #include "cond.h"
5
6 #define MAX 15
7
8 //任务队列
9 typedef struct tast{
10 void*(*pfun) (void *);//回调函数
11 void * arg; //回调函数参数
12 struct task *next;
13 }task_t;
14
15 //线程池
16 typedef struct threadpool{
17 condition_t cond;//互斥量
18 task_t *first; //任务队列的队头
19 task_t *tail; //任务队列队尾
20 int max_thread; //最大线程数
21 int idle; //空闲线程个数
22 int counter; //线程池当前线程个数
23 }threadpool_t;
24
25
26 void threadpool_init(threadpool_t *pool);
27 void* myroute(void *arg);
28 void threadpool_add(threadpool_t *pool,void*(*pfun1)(void *),void *arg1);
29 void threadpool_destroy(threadpool_t *pool);
1 #include "thread.h"
2
3 void threadpool_init(threadpool_t *pool){
4 cond_init(&(pool->cond));
5 pool->first=NULL;
6 pool->tail=NULL;
7 pool->max_thread=MAX;
8 pool->idle=0;
9 pool->counter=0;
10 }
11
12 void* myroute(void *arg){
13 threadpool_t *pool=(threadpool_t *)arg;
14 while(1){
15 cond_lock(&pool->cond);
16 pool->idle++;
17 if(pool->first==NULL){
18 cond_wait(&pool->cond);
19 }
20 pool->idle--;
21
22 if(pool->first!=NULL){
23 task_t *t=pool->first;
24 pool->first=pool->first->next;
25 cond_unlock(&pool->cond);
26
27 (t->pfun)(t->arg);
28 cond_lock(&pool->cond);
29 free(t);
30 }
31 cond_unlock(&pool->cond);
32 }
33 }
34
35 void threadpool_add(threadpool_t *pool,void*(*pfun1)(void *),void *arg1){
36 task_t *new=(task_t *)malloc(sizeof(task_t));
37 new->pfun=pfun1;
38 new->arg=arg1;
39 new->next=NULL;
40 cond_lock(&pool->cond);
41 if(pool->first==NULL){
42 pool->first=new;
43 }else{
44 pool->tail->next=new;
45 }
46 pool->tail=new;
47
48 if(pool->idle>0){
49 cond_signal(&pool->cond);
50 }else if(pool->counter<pool->max_thread){
51 pthread_t tid;
52 pthread_create(&tid,NULL,myroute,(void *)pool);
53 pool->counter++;
54 }
55 cond_unlock(&pool->cond);
56 }
57
58 void threadpool_destroy(threadpool_t *pool){
59 cond_destroy(&pool->cond);
60 }
condition.c
1 #include <pthread.h>
2
3 //互斥量
4 typedef struct condition{
5 pthread_mutex_t mutex;
6 pthread_cond_t cond;
7 }condition_t;
1 #include "cond.h"
2
3 void cond_init(condition_t *condi){
4 pthread_mutex_init(&condi->mutex,NULL);
5 pthread_cond_init(&condi->cond,NULL);
6 }
7
8 void cond_lock(condition_t *condi){
9 pthread_mutex_lock(&condi->mutex);
10 }
11
12 void cond_unlock(condition_t *condi){
13 pthread_mutex_unlock(&condi->mutex);
14 }
15
16 void cond_wait(condition_t *condi){
17 pthread_cond_wait(&condi->cond,&condi->mutex);
18 }
19
20 void cond_signal(condition_t *condi){
21 pthread_cond_signal(&condi->cond);
22 }
23
24 void cond_destroy(condition_t *condi){
25 pthread_mutex_destroy(&condi->mutex);
26 pthread_cond_destroy(&condi->cond);
27 }
main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "thread.h"
4
5
6 void * route(void * arg){
7 int num=*(int *)arg;
8 free(arg);
9 printf("%#X thread say %d runing\n",pthread_self(),num);
10 sleep(1);
11 }
12
13 int main(void){
14 threadpool_t pool;
15 threadpool_init(&pool);
16 int i=0;
17 for(;i<10;i++){
18 int *p=malloc(sizeof(int));
19 *p=i;
20 threadpool_add(&pool,route,(void*)p);
21 }
22 sleep(15);
23 threadpool_destroy(&pool);
24 }