Linux中生产与消费者模型、环形生产与消费者模型、线程池

生产者与消费者模型

通过一个容器来解决生产者与消费者之间的强耦合问题:
生产者与消费者之间不直接通讯,而是通过无锁阻塞队列来进行通讯;生产者生产完数据后不用等待消费者处理,而是直接放到阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列取。 阻塞队列相当于一个缓冲区,平衡了生产者与消费者的处理能力,用来解耦合。

优点:
  1. 支持忙闲不均
  2. 支持并发(先保证安全队列)
  3. 解耦合(让两个模块间减少关联)
BlockingQueue代码实现

注意

  1. 生产者或消费者之间具备互斥关系
  2. 生产者与消费者之间具备同步+互相hi关系
  3. 先进先出
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<pthread.h>
#include<unistd.h>
using namespace std;

#define MAX_QUE 10
#define MAX_THR 4

class BlockQueue{
	private:
		queue<int> _queue;
		int _capacity;
		pthread_cond_t _cond_pro;//生产者条件变量
		pthread_cond_t _cond_con;//消费者条件变量
		pthread_mutex_t _mutex;
	public:
		BlockQueue(int que_num=MAX_QUE):_capacity(que_num){
			pthread_mutex_init(&_mutex,NULL);
			pthread_cond_init(&_cond_pro,NULL);
			pthread_cond_init(&_cond_con,NULL);
		}
		~BlockQueue(){
			pthread_mutex_destroy(&_mutex);
			pthread_cond_destroy(&_cond_pro);
			pthread_cond_destroy(&_cond_con);
		}
		bool QueuePush(int &data){
			pthread_mutex_lock(&_mutex);
			while(_queue.size()==_capacity){
				pthread_cond_wait(&_cond_pro,&_mutex);
			}
			_queue.push(data);
			pthread_mutex_unlock(&_mutex);
			pthread_cond_signal(&_cond_con);
			return true;
		}
		bool QueuePop(int &data){
			pthread_mutex_lock(&_mutex);
			while(_queue.size()==0){
				pthread_cond_wait(&_cond_con,&_mutex);
			}
			data=_queue.front();
			_queue.pop();
			pthread_mutex_unlock(&_mutex);
			pthread_cond_signal(&_cond_pro);
			return true;
		}
};
void *consumer(void *arg){
	BlockQueue *queue=(BlockQueue*)arg;	
	while(1){
		int data;
		queue->QueuePop(data);
		printf("%p..get a data:%d\n",pthread_self(),data);
	}
	return NULL;
}
void *product(void *arg){
	int data=0;
	BlockQueue *queue=(BlockQueue*)arg;	

	while(1){
		queue->QueuePush(data);
		printf("%p__put a data:%d\n",pthread_self(),data++);
                sleep(1);
	}
	return NULL;
}
int main(){
	BlockQueue bq;
	pthread_t ptid[MAX_THR],ctid[MAX_THR];

	int ret;
	for(int i=0;i<MAX_THR;i++){
		ret=pthread_create(&ptid[i],NULL,product,(void*)&bq);
		if(ret!=0){
			cerr<<"pthread create error"<<endl;
			return -1;	
		}
	}
	for(int i=0;i<MAX_THR;i++){
		ret=pthread_create(&ctid[i],NULL,consumer,(void*)&bq);
		if(ret!=0){
			cerr<<"pthread create error\n"<<endl;
			return -1;	
		}
	}

	for(int i=0;i<MAX_THR;i++){
		pthread_join(ptid[i],NULL);
		pthread_join(ctid[i],NULL);
	}
	return 0;
}

环形生产与消费者模型

#include<iostream>
#include<string>
#include<stdio.h>
#include<unistd.h>
#include<vector>
#include<semaphore.h>
#include<pthread.h>
using namespace std;
#define MAX_THR 4
#define MAX_QN 10
class RingQueue{
	private:
		vector<int> _queue;
		int _capacity;
		int _read;
		int _write;
		sem_t sem_lock;
		sem_t sem_con;
		sem_t sem_pro;
	public:
		RingQueue(int max_que=MAX_QN):_capacity(max_que),_queue(max_que),_write(0),_read(0){
			sem_init(&sem_lock,0,1);
			sem_init(&sem_con,0,0);
			sem_init(&sem_pro,0,max_que);

		}
		~RingQueue(){
			sem_destroy(&sem_lock);
			sem_destroy(&sem_pro);
			sem_destroy(&sem_con);
		}
		bool QueuePush(int &data){
			sem_wait(&sem_pro);
			sem_wait(&sem_lock);
			_queue[_write]=data;
			_write=(_write+1)%_capacity;
			sem_post(&sem_lock);
			sem_post(&sem_con);
			return true;
		}
		bool QueuePop(int &data){
			sem_wait(&sem_con);
			sem_wait(&sem_lock);
			data=_queue[_read];		        
			_read=(_read+1)%_capacity;
			sem_post(&sem_lock);
			sem_post(&sem_pro);
			return true;              
		}

};
void *consumer(void *arg){//消费者执行函数
	RingQueue *queue=(RingQueue*)arg;
	while(1){
		int data;
		queue->QueuePop(data);
		printf("%p***get a data:%d\n",pthread_self(),data);
	}
	return NULL;
}

void *productor(void *arg){//生产者执行函数
	RingQueue *queue=(RingQueue*)arg;
	int i=0;	
	while(1){
		queue->QueuePush(i);
		printf("%p---put a data:%d\n",pthread_self(),i++);
		sleep(1);	
	}
	return NULL;
}
int main(){
	RingQueue queue;
	pthread_t ctid[MAX_THR],ptid[MAX_THR];
	for(int i=0;i<MAX_THR;i++){
	      int ret=pthread_create(&ctid[i],NULL,consumer,(void*)&queue);
		if(ret!=0){
			printf("pthread create error\n");
			return -1;	
		}
	}
	for(int i=0;i<MAX_THR;i++){
	      int ret=pthread_create(&ptid[i],NULL,productor,(void*)&queue);
	   	  if(ret!=0){
		    	printf("pthread create error\n");
			    return -1;		
		}
	}

	for(int i=0;i<MAX_THR;i++){
		pthread_join(ctid[i],NULL);
		pthread_join(ptid[i],NULL);
	}
	return 0;
}

线程池

提前创建一批线程(最大数量限制),以及一个线程安全的任务队列,当大量的请求到来后,被添加到任务队列中,而线程池中的线程再不断从任务队列中获取任务进行处理即可。

作用
  1. 避免大量线程的频繁创建与销毁所带来的时间成本。
  2. 避免峰值压力下的线程创建过多导致的导致资源耗尽的风险。(创建有最大数量上限)
实现方法
  1. 一个以上的线程+线程安全的队列
  2. 使用C++封装一个线程池类,向外提供简单的线程池操作接口
代码实现
#include<iostream>
#include<queue>
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
using namespace std;

//任务类的实现
typedef void(*TaskHandler)(int data);
class ThreadTask{
	private:
		int _data;
		TaskHandler _handler;

	public:
		ThreadTask(){}

		ThreadTask(int data,TaskHandler handler)//构造时给定参数
			:_data(data),_handler(handler){}

		void SetTask(int data,TaskHandler handler){
			_data=data;
			_handler=handler;
		}

		void Run(){
			_handler(_data);
		}
};

//线程池的实现
#define MAX_THR 5
class ThreadPool{
	private:
		int thr_num;//线程池中线程的最大数量
		queue<ThreadTask> _task_queue;//队列
		pthread_mutex_t _mutex;//保护队列的安全操作
		pthread_cond_t _cond_con;//实现队列的同步操作---消费者
		pthread_cond_t _cond_pro;//实现队列的同步操作---生产者
		
	private:
		static void *thr_start(void *arg){//只能洋浦一个函数,如果没有static表示是个类成员函数
			ThreadPool *pool=(ThreadPool*)arg;
			while(1){
				pool->ThreadLock();
				while(pool->TaskIsEmpty()){
					pool->ThreadWait();
				}
				ThreadTask tt;
				pool->QueuePop(tt);		
				pool->ThreadUnlock();
				tt.Run();
			}		
			return NULL;
		}
		
	public:	
		void ThreadLock(){
			pthread_mutex_lock(&_mutex);
		}
		void ThreadUnlock(){
			pthread_mutex_unlock(&_mutex);
		}
		void ThreadWait(){
			pthread_cond_wait(&_cond_con,&_mutex);
		}
		void ThreadWakeUp(){
			pthread_cond_signal(&_cond_con);
		}
		bool TaskIsEmpty(){
			return _task_queue.empty();
		}
		bool QueuePop(ThreadTask &tt){
			tt=_task_queue.front();
			_task_queue.pop();
			return true;                
		}
	public:
		ThreadPool(int max_thr=MAX_THR)
			:thr_num(max_thr){}
			
		//线程池的初始化	
		bool PoolInit(){
			pthread_mutex_init(&_mutex,NULL);//锁、条件变量的初始化一定要放在线程创建之前
			pthread_cond_init(&_cond_con,NULL);
			pthread_cond_init(&_cond_pro,NULL);
			
			for(int i=0;i<thr_num;i++){
				pthread_t tid;
				int ret=pthread_create(&tid,NULL,thr_start,(void*)this);
				if(ret!=0){
					cerr<<"pthread create error\n";
					return false;
				}
				pthread_detach(tid);
			}
			return  true;
		}
        //向任务队列中添加队列
		bool TaskPush(ThreadTask &tt){
			pthread_mutex_lock(&_mutex);
			_task_queue.push(tt);
			pthread_mutex_unlock(&_mutex);
			pthread_cond_signal(&_cond_con);
			return true;
		}
};

//调用函数
void test(int data){
	srand(data);
	int sec=rand()%5;
	printf("thread:%p---get data:%d,sleep %d sec\n",pthread_self(),data,sec);
	sleep(sec);
}

int main(){
	ThreadPool pool;
	pool.PoolInit();
	for(int i=0;i<10;i++){
		ThreadTask task(i,test);
		pool.TaskPush(task);
	}
	while(1){
		sleep(1);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值