收到前几天有的小伙伴提出的疑问,你生产者消费者模型有什么作用,生产者生产一个数据,消费者消费一个数据,这有什么作用呀。那么小编就在之前的基础上增加一点难度,生产者创建一个字符串,消费者翻译一个字符串,当然我用的在阻塞队列中加入的任务。代码如下:
BlockQueue.hpp
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <queue>
namespace Ns_Block
{
template <class T>
class BlockQueue
{
private:
bool IsEmpty()
{
return _bq.empty();
}
bool IsFill()
{
return _bq.size() == 5;
}
void Lock()
{
pthread_mutex_lock(&_mutex);
}
void UnLock()
{
pthread_mutex_unlock(&_mutex);
}
void WaitProducter()
{
pthread_cond_wait(&_is_empty, &_mutex);
}
void WaitConsumer()
{
pthread_cond_wait(&_is_fill, &_mutex);
}
void WackConsumer()
{
pthread_cond_signal(&_is_fill);
}
void WackProducter()
{
pthread_cond_signal(&_is_empty);
}
public:
BlockQueue(size_t cap = 5)
: _cap(cap)
{
pthread_mutex_init(&_mutex, nullptr);
pthread_cond_init(&_is_empty, nullptr);
pthread_cond_init(&_is_fill, nullptr);
}
void Push(const T &val)
{
Lock();
while (IsFill()) //判断是否为满,满了不能在生产了。
{
WaitProducter(); //满了让生产者等待
}
_bq.push(val);
WackConsumer(); //唤醒消费者
UnLock();
}
void Pop(T *out)
{
Lock();
while (IsEmpty()) //判断是否为空,为空不能消费了
{
WaitConsumer(); //为空让消费者等待
}
*out = _bq.front();
_bq.pop();
WackProducter(); //唤醒生产者
UnLock();
}
~BlockQueue()
{
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_is_empty);
pthread_cond_destroy(&_is_fill);
}
private:
pthread_mutex_t _mutex;
pthread_cond_t _is_empty; //条件变量,是否为空
pthread_cond_t _is_fill; //条件变量,是否为满
std::queue<T> _bq;
size_t _cap; //容量
};
}
阻塞队列的框架还是没变。
Task.hpp
#include<iostream>
#include <map>
namespace Ns_Task
{
template<class K,class V>
class task
{
public:
task()
{
}
task(const std::pair<K,V> &kv)
// :_key(key)
// ,_val(val)
:_kv(kv)
{
// _mp.insert(std::make_pair(_key,_key));
_mp.insert(_kv);
}
const V& run()
{
/* auto it = _mp.begin();
while (it != _mp.end())
{
if(it->first == key)
{
// std::cout<<"找到了"<<std::endl;
std::cout << it->first << ":" << it->second << std::endl;
}
else
{
std::cout<<"没有找到"<<std::endl;
}
++it;
}
*/
auto it = _mp.begin();
//std::cout<< "消费者翻译字符串:"<<it->second<<std::endl;
return it->second;
}
~task()
{
}
private:
// K _key;
// V _val;
std::pair<K,V> _kv;
std::map<K,V> _mp;
};
}
Cptest.cpp
#include"BlockQueue.hpp"
#include<time.h>
#include"Task.hpp"
#include<vector>
static std::vector<std::pair<std::string,std::string> >vv { {"sort","排序"},
{"map","地图"} ,
{"left","剩余"},
{"right","右边"}
};
static std::vector<std::string> v1{"sort","left","map","right"};
void *consumer(void *args)
{
Ns_Block::BlockQueue<Ns_Task::task<std::string,std::string> > * bq \
= (Ns_Block::BlockQueue<Ns_Task::task<std::string,std::string> > *)args;
while(true) //消费者一定是在不断消费
{
Ns_Task::task<std::string, std::string> t;
bq->Pop(&t);
std::cout<<"消费者查找翻译字符串:"<<t.run()<<std::endl;
/*
int data = 0;
bq->Pop(&data);
std::cout<<"消费者消费数据:"<<data<<std::endl;
*/
}
}
void *producter(void *args)
{
Ns_Block::BlockQueue<Ns_Task::task<std::string,std::string> > * bq \
= (Ns_Block::BlockQueue<Ns_Task::task<std::string,std::string> > *)args;
while(true) //生产者一定是在不断生产
{
// std::string s1 ="sort",s2="排序";
int index = rand()% 4;
Ns_Task::task<std::string, std::string> t(vv[index]);
std::cout<<"生产者生产字符串:"<<vv[index].first<<std::endl;
bq->Push(t);
sleep(2);
/*
int data = rand() % 20 + 1;
bq->Push(data);
std::cout<<"生产者生产数据:"<<data<<std::endl;
sleep(2);
*/
}
}
int main()
{
pthread_t c,p; //创建一个消费者一个生产者线程
Ns_Block::BlockQueue<Ns_Task::task<std::string,std::string> > * bq = \
new Ns_Block::BlockQueue<Ns_Task::task<std::string,std::string> >();
pthread_create(&c,nullptr,consumer,(Ns_Block::BlockQueue<Ns_Task::task<std::string,std::string> > *)bq);
pthread_create(&p,nullptr,producter,(Ns_Block::BlockQueue<Ns_Task::task<std::string,std::string> >*)bq);
pthread_join(c,nullptr);
pthread_join(p,nullptr);
return 0;
}
我举这个例子,只是想说明,框架都是死的,但是人时活的,我现在可以在阻塞队列加入任务,那么这个任务从哪里来,都是根据需求决定的,可以不可以时打游戏很多用户同时请求,分配任务去处理呢,那这个任务是不是也可以去访问数据库等等,这些就需要小伙伴发挥想象能力,一个项目不也是满足实际需求来决定的。其实越往后小编越能体会到框架还是很厉害的,框架只要搭建起来,只需填充代码就行,所有为什么java开发软件的速率比较快,周期短,还不时java有自己的框架,但是这就是我不怎么喜欢java的原因把,把人的思维搞死了,我还是喜欢自由的语言。具体怎么搭建框架,小编现在也没有搞过,能力有限...。