线程池的简单实现

几个基本的线程函数:(本人有强迫症,为了分清返回值、函数名、参数列表,间距有点大,用的时候不要这样)

线程操纵函数 

1 int  pthread_create  (pthread_t *tidp, const pthread_attr_t *attr, (void*)(*start_rtn)(void *), void *arg); //创建

2 void pthread_exit    (void *retval);            //终止自身

3 int  pthread_cancel  (pthread_t tid);             //终止其他.发送终止信号后目标线程不一定终止,要调用join函数等待

4 int  pthread_join    (pthread_t tid, void **retval);   //阻塞并等待其他线程

属性

1 int  pthread_attr_init            (pthread_attr_t *attr);           //初始化属性 2 int  pthread_attr_setdetachstate  (pthread_attr_t *attr, int detachstate); //设置分离状态 3 int  pthread_attr_destroy         (pthread_attr_t *attr);           //销毁属性

 

同步函数
互斥锁

1 int pthread_mutex_init    (pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);  //初始化锁

2 int pthread_mutex_destroy (pthread_mutex_t *mutex);  //销毁锁

3 int pthread_mutex_lock    (pthread_mutex_t *mutex);  //加锁

4 int pthread_mutex_trylock (pthread_mutex_t *mutex);  //尝试加锁,上面lock的非阻塞版本

5 int pthread_mutex_unlock  (pthread_mutex_t *mutex);  //解锁

条件变量

1 int pthread_cond_init    (pthread_cond_t *cv, const pthread_condattr_t *cattr);  //初始化

2 int pthread_cond_destroy (pthread_cond_t *cond);                                 //销毁 

3 int pthread_cond_wait    (pthread_cond_t *cond, pthread_mutex_t *mutex);         //等待条件

4 int pthread_cond_signal  (pthread_cond_t *cond);                                 //通知,唤醒第一个调用pthread_cond_wait()而进入睡眠的线程

工具函数

1 int       pthread_equal  (pthread_t t1, pthread_t t2); //比较线程ID

2 int pthread_detach (pthread_t tid);              //分离线程

3 pthread_t pthread_self   (void);                       //自身ID

 

上述代码中,线程的cancel和join,以及最后的工具函数,这些函数的参数都为结构体变量,其他的函数参数都是结构体变量指针;品味一下,参数为指针的,因为都需要改变结构体的内容,而参数为普通变量的,则只需要读内容即可。

 

线程池的优点可以自行百度一下, 一个线程池包括4个部分:

1、线程池管理器:用于创建、管理、销毁线程池
2、工作线程:线程池中线程
3、任务接口:线程要调用的函数,任务的具体实现函数
4、任务队列:用于存放没有处理的任务。提供一种缓冲机制。
 

线程池代码: 

  1 #include <stdio.h>

  2 #include <stdlib.h>

  3 #include <pthread.h>    //linux环境中多线程的头文件,非C语言标准库,编译时最后要加 -lpthread 调用动态链接库

  4 

  5 //任务链表的结构

  6 typedef struct worker 

  7 {

  8     void  *(*process) (void *arg);   //工作函数

  9     void  *arg;                      //函数的参数

 10     struct worker *next;

 11 }CThread_worker;

 12 

 13 //线程池的管理结构

 14 typedef struct 

 15 {

 16     pthread_mutex_t queue_lock;     //互斥锁

 17     pthread_cond_t  queue_ready;    //条件变量/信号量

 18 

 19     CThread_worker *queue_head;     //指向工作链表的头结点,临界区

 20     int cur_queue_size;             //记录链表中工作的数量,临界区

 21 

 22     int max_thread_num;             //最大线程数

 23     pthread_t *threadid;            //线程ID

 24 

 25     int shutdown;                   //开关

 26 }CThread_pool;

 27 

 28 static CThread_pool *pool = NULL;   //一个线程池变量

 29 int pool_add_worker(void *(*process)(void *arg), void *arg);    //负责向工作链表中添加实际的工作

 30 void *thread_routine(void *arg);    //线程例程

 31 

 32 //线程池初始化

 33 void

 34 pool_init(int max_thread_num)

 35 {

 36     int i = 0;

 37 

 38     pool = (CThread_pool *) malloc (sizeof(CThread_pool));    //创建线程池

 39 

 40     pthread_mutex_init(&(pool->queue_lock),  NULL);     //互斥锁初始化,参数为锁的地址

 41     pthread_cond_init( &(pool->queue_ready), NULL);     //条件变量初始化,参数为变量地址

 42 

 43     pool->queue_head = NULL;

 44     pool->cur_queue_size = 0;

 45 

 46     pool->max_thread_num = max_thread_num;

 47     pool->threadid = (pthread_t *)malloc(max_thread_num * sizeof(pthread_t));

 48     for (i = 0; i < max_thread_num; i++) 

 49     {

 50         pthread_create(&(pool->threadid[i]), NULL, thread_routine, NULL);  //创建线程, 参数为线程ID变量地址、属性、例程、参数

 51     }

 52 

 53     pool->shutdown = 0;

 54 }

 55 

 56 //例程,调用具体的工作函数

 57 void *

 58 thread_routine(void *arg)

 59 {

 60     //线程开始

 61     while(1)

 62     {

 63         pthread_mutex_lock(&(pool->queue_lock));    //从工作链表中取工作,要先加互斥锁,参数为锁地址

 64 

 65         while(pool->cur_queue_size == 0 && !pool->shutdown) 

 66         {   //链表为空,线程等待

 67             pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock));   //等待资源,信号量用于通知。会释放第二个参数的锁,以供添加;函数返回时重新加锁。

 68         }

 69 

 70         if(pool->shutdown) 

 71         {

 72             pthread_mutex_unlock(&(pool->queue_lock));          //结束开关开启,释放锁并退出线程

 73             pthread_exit(NULL);     //参数为void *

 74         }

 75     

 76         //线程准备工作

 77         --pool->cur_queue_size;

 78         CThread_worker *worker = pool->queue_head;

 79         pool->queue_head = worker->next;

 80 

 81         pthread_mutex_unlock (&(pool->queue_lock));     //获取一个工作后释放锁

 82 

 83 

 84         (*(worker->process))(worker->arg);      //做工作

 85         free(worker);

 86         worker = NULL;

 87     }

 88 

 89     pthread_exit(NULL);

 90 }

 91 

 92 //销毁线程池

 93 int

 94 pool_destroy()

 95 {

 96     if(pool->shutdown)      //检测结束开关是否开启,若开启,则所有线程会自动退出

 97         return -1;

 98     pool->shutdown = 1;

 99 

100     pthread_cond_broadcast( &(pool->queue_ready) );     //广播,唤醒所有线程,准备退出

101 

102     int i;

103     for(i = 0; i < pool->max_thread_num; ++i)

104         pthread_join(pool->threadid[i], NULL);  //主线程等待所有线程退出,只有join第一个参数不是指针,第二个参数类型是void **,接收exit的返回值,需要强制转换

105     free(pool->threadid);

106 

107     CThread_worker *head = NULL;

108     while(pool->queue_head != NULL)            //释放未执行的工作链表剩余结点

109     {

110         head = pool->queue_head;

111         pool->queue_head = pool->queue_head->next;

112         free(head);

113     }

114 

115     pthread_mutex_destroy(&(pool->queue_lock));     //销毁锁和条件变量

116     pthread_cond_destroy(&(pool->queue_ready));

117 

118     free(pool);

119     pool=NULL;

120     return 0;

121 }

122 

123 void *

124 myprocess(void *arg)

125 {

126     printf("threadid is 0x%x, working on task %d\n", (int)pthread_self(), *(int*)arg);    //工作函数,添加实际的代码,用sleep来代替

127     sleep (1);

128     return NULL;

129 }

130 

131 //添加工作

132 int

133 pool_add_worker(void *(*process)(void *arg), void *arg)

134 {

135     CThread_worker *newworker = (CThread_worker *) malloc(sizeof(CThread_worker));

136     newworker->process = process;   //具体的工作函数

137     newworker->arg = arg;

138     newworker->next = NULL;

139 

140     pthread_mutex_lock( &(pool->queue_lock) );      //加锁

141 

142     CThread_worker *member = pool->queue_head;      //插入链表尾部

143     if( member != NULL ) 

144     {

145         while( member->next != NULL )

146             member = member->next;

147         member->next = newworker;

148     }

149     else 

150     {

151         pool->queue_head = newworker;

152     }

153     ++pool->cur_queue_size;

154 

155     pthread_mutex_unlock( &(pool->queue_lock) );   //解锁

156 

157     pthread_cond_signal( &(pool->queue_ready) );   //通知一个等待的线程

158     return 0;

159 }

160 

161 int

162 main(int argc, char **argv)

163 {

164     pool_init(3);   //主线程创建线程池,3个线程

165 

166     int *workingnum = (int *) malloc(sizeof(int) * 10);

167     int i;

168     for(i = 0; i < 10; ++i) 

169     {

170         workingnum[i] = i;

171         pool_add_worker(myprocess, &workingnum[i]);     //主线程负责添加工作,10个工作

172     }

173 

174     sleep (5);

175     pool_destroy();     //销毁线程池

176     free (workingnum);

177 

178     return 0;

179 }

 

 

你可能感兴趣的:(线程池)