生产者消费者编程实现,采用了线程池以及信号量技术。
线程的概念就不多说,首先说一下多线程的好处:多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。
那么为什么又需要线程池呢?
我们知道应用程序创建一个对象,然后销毁对象是很耗费资源的。创建线程,销毁线程,也是如此。因此,我们就预先生成一些线程,等到我们使用的时候在进行调度,于是,一些"池化资源"技术就这样的产生了。
一般一个简单线程池至少包含下列组成部分。
1)线程池管理器(ThreadPoolManager):用于创建并管理线程池
2)工作线程(WorkThread):线程池中线程
3)任务接口(Task):每个任务必须实现的接口,以供工作线程调度任务的执行。
4)任务队列:用于存放没有处理的任务。提供一种缓冲机制。
图示:图1 线程池图解
生产者消费者模型C语言代码实现:
thread_pool_pv.h:
//线程池编程实现
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>//信号量sem_t
#include <pthread.h>
//任务接口,线程调用的函数
typedef void* (*FUNC)(void *arg);
//任务数据结构
typedef struct thread_pool_job_s{
FUNC function;//线程调用的函数
void *arg;//函数参数
struct thread_pool_job_s *pre;//指向上一个节点
struct thread_pool_job_s *next;//指向下一个节点
}thread_pool_job;
//工作队列
typedef struct thread_pool_job_queue_s{
thread_pool_job *head;//队列头指针
thread_pool_job *tail;//队列尾指针
int num;//任务数目
sem_t *quene_sem;//信号量
}thread_pool_job_queue;
//线程池(存放消费者进程)
typedef struct thread_pool_s{
pthread_t *threads;//线程
int threads_num;//线程数目
thread_pool_job_queue *job_queue;//指向工作队列的指针
}thread_pool;
//typedef struct thread_data_s{
// pthread_mutex_t *mutex_t;//互斥量
// thread_pool *tp_p;//指向线程池的指针
//}thread_data;
//初始化线程池
thread_pool* tp_init(int thread_num);
//初始化工作队列
int tp_job_quene_init(thread_pool *tp);
//向工作队列中添加一个元素
void tp_job_quene_add(thread_pool *tp,thread_pool_job *new_job);
//向线程池中添加一个工作项
int tp_add_work(thread_pool *tp,void *(*func_p)(void *),void *arg);
//取得工作队列的最后个节点
thread_pool_job* tp_get_lastjob(thread_pool *tp);
//删除工作队列的最后个节点
int tp_delete__lastjob(thread_pool *tp);
//销毁线程池
void tp_destroy(thread_pool *tp);
//消费者线程函数
void* tp_thread_func(thread_pool *tp);
//生产者线程执行函数
void* thread_func_producer(thread_pool *tp);
#endif
thread_pool_pv.c:
//线程池编程实现
#include "thread_pool.h"
//互斥量,用于对工作队列的访问
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//标记线程池是否处于可用状态
static int tp_alive = 1;
//初始化线程池
thread_pool* tp_init(int thread_num){
thread_pool *tp;
int i;
if(thread_num < 1)
thread_num = 1;
tp = (thread_pool *)malloc(sizeof(thread_pool));
//判断内存分配是否成功
if(NULL == tp){
printf("ERROR:allocate memory for thread_pool failed\n");
return NULL;
}
tp->threads_num = thread_num;
//分配线程所占内存空间
tp->threads = (pthread_t*)malloc(thread_num * sizeof(pthread_t));
//判断内存分配是否成功
if(NULL == tp->threads){
printf("ERROR:allocate memory for threads in thread pool failed\n");
return NULL;
}
if(tp_job_quene_init(tp))
return NULL;
tp->job_queue->quene_sem = (sem_t *)malloc(sizeof(sem_t));
sem_init(tp->job_queue->quene_sem,0,0);//信号量初始化
//初始化线程
for(i = 0;i < thread_num;++i){
pthread_create(&(tp->threads[i]),NULL,(void *)tp_thread_func,(void *)tp);
}
return tp;
}
//初始化工作队列
int tp_job_quene_init(thread_pool *tp){
tp->job_queue = (thread_pool_job_queue *)malloc(sizeof(thread_pool_job_queue));
if(NULL == tp->job_queue){
return -1;
}
tp->job_queue->head = NULL;
tp->job_queue->tail = NULL;
tp->job_queue->num = 0;
return 0;
}
//线程函数
void* tp_thread_func(thread_pool *tp){
FUNC function;
void *arg_buf;
thread_pool_job *job_p;
while(tp_alive){
//线程阻塞,等待信号量
if(sem_wait(tp->job_queue->quene_sem)){
printf("thread waiting for semaphore....\n");
exit(1);
}
if(tp_alive){
pthread_mutex_lock(&mutex);
job_p = tp_get_lastjob(tp);
if(NULL == job_p){
pthread_mutex_unlock(&mutex);
continue;
}
function = job_p->function;
arg_buf = job_p->arg;
if(tp_delete__lastjob(tp))
return;
pthread_mutex_unlock(&mutex);
//运行指定的线程函数
printf("consumer...get a job from job quene and run it!\n");
function(arg_buf);
free(job_p);
}
else
return;
}
return;
}
//向工作队列中添加一个元素
void tp_job_quene_add(thread_pool *tp,thread_pool_job *new_job){
new_job->pre = NULL;
new_job->next = NULL;
thread_pool_job *old_head_job = tp->job_queue->head;
if(NULL == old_head_job){
tp->job_queue->head = new_job;
tp->job_queue->tail = new_job;
}
else{
old_head_job->pre = new_job;
new_job->next = old_head_job;
tp->job_queue->head = new_job;
}
++(tp->job_queue->num);
sem_post(tp->job_queue->quene_sem);
}
//取得工作队列的最后一个节点
thread_pool_job* tp_get_lastjob(thread_pool *tp){
return tp->job_queue->tail;
}
//删除工作队列的最后个节点
int tp_delete__lastjob(thread_pool *tp){
if(NULL == tp)
return -1;
thread_pool_job *last_job = tp->job_queue->tail;
if(0 == tp->job_queue->num){
return -1;
}
else if(1 == tp->job_queue->num){
tp->job_queue->head = NULL;
tp->job_queue->tail = NULL;
}
else{
last_job->pre->next = NULL;
tp->job_queue->tail = last_job->pre;
}
//修改相关变量
--(tp->job_queue->num);
return 0;
}
//向线程池中添加一个工作项
int tp_add_work(thread_pool *tp,void *(*func_p)(void *),void *arg){
thread_pool_job *new_job = (thread_pool_job *)malloc(sizeof(thread_pool_job));
if(NULL == new_job){
printf("ERROR:allocate memory for new job failed!\n");
exit(1);
}
new_job->function = func_p;
new_job->arg = arg;
pthread_mutex_lock(&mutex);
tp_job_quene_add(tp,new_job);
pthread_mutex_unlock(&mutex);
}
//销毁线程池
void tp_destroy(thread_pool *tp){
int i;
tp_alive = 0;
//等待线程运行结束
//sleep(10);
for(i = 0;i < tp->threads_num;++i){
pthread_join(tp->threads[i],NULL);
}
free(tp->threads);
if(sem_destroy(tp->job_queue->quene_sem)){
printf("ERROR:destroy semaphore failed!\n");
}
free(tp->job_queue->quene_sem);
//删除job队列
thread_pool_job *current_job = tp->job_queue->tail;
while(tp->job_queue->num){
tp->job_queue->tail = current_job->pre;
free(current_job);
current_job = tp->job_queue->tail;
--(tp->job_queue->num);
}
tp->job_queue->head = NULL;
tp->job_queue->tail = NULL;
}
//自定义线程执行函数
void* thread_func1(){
printf("Task1 running...by Thread :%u\n",(unsigned int)pthread_self());
}
//自定义线程执行函数
void* thread_func2(){
printf("Task2 running...by Thread :%u\n",(unsigned int)pthread_self());
}
//生产者线程执行函数
void* thread_func_producer(thread_pool *tp){
while(1){
printf("producer...add a job(job1) to job quene!\n");
tp_add_work(tp,(void*)thread_func1,NULL);
sleep(1);
printf("producer...add a job(job2) to job quene!\n");
tp_add_work(tp,(void*)thread_func2,NULL);
}
}
int main(){
thread_pool *tp = tp_init(5);
int i;
int arg = 7;
pthread_t producer_thread_id;//生产者线程ID
pthread_create(&producer_thread_id,NULL,(void *)thread_func_producer,(void *)tp);
pthread_join(producer_thread_id,NULL);
tp_destroy(tp);
return 0;
}
运行结果: