【转】【Linux】生产者消费者编程实现-线程池+信号量 - 江南烟雨 - 博客频道 - CSDN.NET

出处:http://blog.csdn.net/xiajun07061225/article/details/11889423

生产者消费者编程实现,采用了线程池以及信号量技术。


线程的概念就不多说,首先说一下多线程的好处:多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。

 

那么为什么又需要线程池呢?

 

我们知道应用程序创建一个对象,然后销毁对象是很耗费资源的。创建线程,销毁线程,也是如此。因此,我们就预先生成一些线程,等到我们使用的时候在进行调度,于是,一些"池化资源"技术就这样的产生了。



一般一个简单线程池至少包含下列组成部分。

1)        线程池管理器(ThreadPoolManager:用于创建并管理线程池

2)        工作线程(WorkThread线程池中线程

3)        任务接口(Task:每个任务必须实现的接口,以供工作线程调度任务的执行。

4)        任务队列:用于存放没有处理的任务。提供一种缓冲机制。

图示:


图1 线程池图解


生产者消费者模型C语言代码实现:

thread_pool_pv.h:

  1. //线程池编程实现  
  2. #ifndef THREAD_POOL_H  
  3. #define THREAD_POOL_H  
  4.   
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <semaphore.h>//信号量sem_t  
  8. #include <pthread.h>  
  9.   
  10.   
  11. //任务接口,线程调用的函数  
  12. typedef void* (*FUNC)(void *arg);  
  13.   
  14. //任务数据结构  
  15. typedef struct thread_pool_job_s{  
  16.         FUNC function;//线程调用的函数  
  17.         void *arg;//函数参数  
  18.         struct thread_pool_job_s *pre;//指向上一个节点  
  19.         struct thread_pool_job_s *next;//指向下一个节点  
  20. }thread_pool_job;  
  21.   
  22. //工作队列  
  23. typedef struct thread_pool_job_queue_s{  
  24.         thread_pool_job *head;//队列头指针  
  25.         thread_pool_job *tail;//队列尾指针  
  26.         int num;//任务数目  
  27.         sem_t *quene_sem;//信号量  
  28. }thread_pool_job_queue;  
  29.   
  30. //线程池(存放消费者进程)  
  31. typedef struct thread_pool_s{  
  32.         pthread_t *threads;//线程  
  33.         int threads_num;//线程数目  
  34.         thread_pool_job_queue *job_queue;//指向工作队列的指针  
  35. }thread_pool;  
  36.   
  37. //typedef struct thread_data_s{  
  38. //      pthread_mutex_t *mutex_t;//互斥量  
  39. //      thread_pool *tp_p;//指向线程池的指针  
  40. //}thread_data;  
  41.   
  42. //初始化线程池  
  43. thread_pool* tp_init(int thread_num);  
  44.   
  45. //初始化工作队列  
  46. int tp_job_quene_init(thread_pool *tp);  
  47.   
  48. //向工作队列中添加一个元素  
  49. void tp_job_quene_add(thread_pool *tp,thread_pool_job *new_job);  
  50.   
  51. //向线程池中添加一个工作项  
  52. int tp_add_work(thread_pool *tp,void *(*func_p)(void *),void *arg);  
  53.   
  54. //取得工作队列的最后个节点  
  55. thread_pool_job* tp_get_lastjob(thread_pool *tp);  
  56.   
  57. //删除工作队列的最后个节点  
  58. int tp_delete__lastjob(thread_pool *tp);  
  59.   
  60. //销毁线程池  
  61. void tp_destroy(thread_pool *tp);  
  62.   
  63. //消费者线程函数  
  64. void* tp_thread_func(thread_pool *tp);  
  65.   
  66. //生产者线程执行函数  
  67. void* thread_func_producer(thread_pool *tp);  
  68.   
  69. #endif  



thread_pool_pv.c:

  1. //线程池编程实现  
  2. #include "thread_pool.h"  
  3.   
  4. //互斥量,用于对工作队列的访问  
  5. pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  
  6.   
  7. //标记线程池是否处于可用状态  
  8. static int tp_alive = 1;  
  9.   
  10. //初始化线程池  
  11. thread_pool* tp_init(int thread_num){  
  12.         thread_pool *tp;  
  13.         int i;  
  14.   
  15.         if(thread_num < 1)  
  16.                 thread_num = 1;  
  17.   
  18.         tp = (thread_pool *)malloc(sizeof(thread_pool));  
  19.         //判断内存分配是否成功  
  20.         if(NULL == tp){  
  21.                 printf("ERROR:allocate memory for thread_pool failed\n");  
  22.                 return NULL;  
  23.         }  
  24.         tp->threads_num = thread_num;  
  25.         //分配线程所占内存空间  
  26.         tp->threads = (pthread_t*)malloc(thread_num * sizeof(pthread_t));  
  27.         //判断内存分配是否成功  
  28.         if(NULL == tp->threads){  
  29.                 printf("ERROR:allocate memory for threads in thread pool failed\n");  
  30.                 return NULL;  
  31.         }  
  32.           
  33.         if(tp_job_quene_init(tp))  
  34.                 return NULL;  
  35.           
  36.         tp->job_queue->quene_sem = (sem_t *)malloc(sizeof(sem_t));  
  37.         sem_init(tp->job_queue->quene_sem,0,0);//信号量初始化  
  38.   
  39.         //初始化线程  
  40.         for(i = 0;i < thread_num;++i){  
  41.                 pthread_create(&(tp->threads[i]),NULL,(void *)tp_thread_func,(void *)tp);  
  42.         }  
  43.   
  44.         return tp;  
  45. }  
  46.   
  47. //初始化工作队列  
  48. int tp_job_quene_init(thread_pool *tp){  
  49.         tp->job_queue = (thread_pool_job_queue *)malloc(sizeof(thread_pool_job_queue));  
  50.   
  51.         if(NULL == tp->job_queue){  
  52.                 return -1;  
  53.         }  
  54.   
  55.         tp->job_queue->head = NULL;  
  56.         tp->job_queue->tail = NULL;  
  57.         tp->job_queue->num = 0;  
  58.   
  59.         return 0;  
  60. }  
  61.   
  62. //线程函数  
  63. void* tp_thread_func(thread_pool *tp){  
  64.         FUNC function;  
  65.         void *arg_buf;  
  66.         thread_pool_job *job_p;  
  67.   
  68.         while(tp_alive){  
  69.                 //线程阻塞,等待信号量  
  70.                 if(sem_wait(tp->job_queue->quene_sem)){  
  71.                         printf("thread waiting for semaphore....\n");  
  72.                         exit(1);  
  73.                 }  
  74.                 if(tp_alive){  
  75.                         pthread_mutex_lock(&mutex);  
  76.                         job_p = tp_get_lastjob(tp);  
  77.                         if(NULL == job_p){  
  78.                                 pthread_mutex_unlock(&mutex);  
  79.                                 continue;  
  80.                         }  
  81.                         function = job_p->function;  
  82.                         arg_buf = job_p->arg;  
  83.                         if(tp_delete__lastjob(tp))  
  84.                                 return;  
  85.                         pthread_mutex_unlock(&mutex);  
  86.                         //运行指定的线程函数  
  87.                         printf("consumer...get a job from job quene and run it!\n");  
  88.                         function(arg_buf);  
  89.                         free(job_p);  
  90.                 }  
  91.                 else  
  92.                         return;  
  93.         }  
  94.   
  95.         return;  
  96. }  
  97.   
  98. //向工作队列中添加一个元素  
  99. void tp_job_quene_add(thread_pool *tp,thread_pool_job *new_job){  
  100.         new_job->pre = NULL;  
  101.         new_job->next = NULL;  
  102.         thread_pool_job *old_head_job = tp->job_queue->head;  
  103.   
  104.         if(NULL == old_head_job){  
  105.                 tp->job_queue->head = new_job;  
  106.                 tp->job_queue->tail = new_job;  
  107.         }  
  108.         else{  
  109.                 old_head_job->pre = new_job;  
  110.                 new_job->next = old_head_job;  
  111.                 tp->job_queue->head = new_job;  
  112.         }  
  113.   
  114.         ++(tp->job_queue->num);  
  115.   
  116.         sem_post(tp->job_queue->quene_sem);  
  117. }  
  118.   
  119. //取得工作队列的最后一个节点  
  120. thread_pool_job* tp_get_lastjob(thread_pool *tp){  
  121.         return tp->job_queue->tail;  
  122. }  
  123.   
  124. //删除工作队列的最后个节点  
  125. int tp_delete__lastjob(thread_pool *tp){  
  126.         if(NULL == tp)  
  127.                 return -1;  
  128.   
  129.         thread_pool_job *last_job = tp->job_queue->tail;  
  130.         if(0 == tp->job_queue->num){  
  131.                 return -1;  
  132.         }  
  133.         else if(1 == tp->job_queue->num){  
  134.                 tp->job_queue->head = NULL;  
  135.                 tp->job_queue->tail = NULL;  
  136.         }  
  137.         else{  
  138.                 last_job->pre->next = NULL;  
  139.                 tp->job_queue->tail = last_job->pre;  
  140.         }  
  141.   
  142.         //修改相关变量  
  143.         --(tp->job_queue->num);  
  144.   
  145.         return 0;  
  146. }  
  147.   
  148. //向线程池中添加一个工作项  
  149. int tp_add_work(thread_pool *tp,void *(*func_p)(void *),void *arg){  
  150.         thread_pool_job *new_job = (thread_pool_job *)malloc(sizeof(thread_pool_job));  
  151.         if(NULL == new_job){  
  152.                 printf("ERROR:allocate memory for new job failed!\n");  
  153.                 exit(1);  
  154.         }  
  155.         new_job->function = func_p;  
  156.         new_job->arg = arg;  
  157.         pthread_mutex_lock(&mutex);  
  158.         tp_job_quene_add(tp,new_job);  
  159.         pthread_mutex_unlock(&mutex);  
  160. }  
  161.   
  162.   
  163. //销毁线程池  
  164. void tp_destroy(thread_pool *tp){  
  165.         int i;  
  166.         tp_alive = 0;  
  167.           
  168.         //等待线程运行结束  
  169.         //sleep(10);  
  170.         for(i = 0;i < tp->threads_num;++i){  
  171.                 pthread_join(tp->threads[i],NULL);  
  172.         }  
  173.         free(tp->threads);  
  174.   
  175.         if(sem_destroy(tp->job_queue->quene_sem)){  
  176.                 printf("ERROR:destroy semaphore failed!\n");  
  177.         }  
  178.         free(tp->job_queue->quene_sem);  
  179.   
  180.         //删除job队列  
  181.         thread_pool_job *current_job = tp->job_queue->tail;  
  182.         while(tp->job_queue->num){  
  183.                 tp->job_queue->tail = current_job->pre;  
  184.                 free(current_job);  
  185.                 current_job = tp->job_queue->tail;  
  186.                 --(tp->job_queue->num);  
  187.         }  
  188.         tp->job_queue->head = NULL;  
  189.         tp->job_queue->tail = NULL;  
  190. }  
  191.   
  192. //自定义线程执行函数  
  193. void* thread_func1(){  
  194.         printf("Task1 running...by Thread  :%u\n",(unsigned int)pthread_self());  
  195. }  
  196.   
  197. //自定义线程执行函数  
  198. void* thread_func2(){  
  199.         printf("Task2 running...by Thread  :%u\n",(unsigned int)pthread_self());  
  200. }  
  201.   
  202. //生产者线程执行函数  
  203. void* thread_func_producer(thread_pool *tp){  
  204.         while(1){  
  205.                 printf("producer...add a job(job1) to job quene!\n");  
  206.                 tp_add_work(tp,(void*)thread_func1,NULL);  
  207.                 sleep(1);  
  208.                 printf("producer...add a job(job2) to job quene!\n");  
  209.                 tp_add_work(tp,(void*)thread_func2,NULL);  
  210.         }  
  211. }  
  212.   
  213. int main(){  
  214.         thread_pool *tp = tp_init(5);  
  215.         int i;  
  216.         int arg = 7;  
  217.         pthread_t producer_thread_id;//生产者线程ID  
  218.         pthread_create(&producer_thread_id,NULL,(void *)thread_func_producer,(void *)tp);  
  219.   
  220.         pthread_join(producer_thread_id,NULL);  
  221.         tp_destroy(tp);  
  222.   
  223.         return 0;  
  224. }  


运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值