作为一名程序员,我想我们应该都写过producer和consumer的模型,应为他的用途实在是太广泛了,比如之前服务器里使用到的actor队列,还有一些对于计算量比较大的任务,都是前端快速接受请求,放到队列,然后后面的线程池取出队列执行并异步返回,都是使用的producer和consumer方式来实现的,我简单的画了一张图:
在代码层面的实现无非是用一个队列,然后再producer和consumer在写入和读取时两端加锁,使用condition实现等待,以此来协调producer,consumer的工作,如果用一个现实生活中的例子来解释的话,就像是代理销售产品,producer就是工厂,中间的队列就是代理商,我们就是消费者,从运营成本上来讲,这种方式加大了消费者的支出,因为代理商要获得收益,那可不可以我们直接去工厂预定他们的产品,然后根据每一个用户们的需求在原来的基础上再DIY一下,最后给consumer呢,答案是可以的,而且还能保证绝对的公平,不信你可以看下面实现:
使用c++中的function/async/promise/packaged_task说白了就是异步回调函数,和feture来实现这种模型。
下面是伪代码的实现,看得懂就ok了
生产者,如果你想的话可以做成一个队列
class producer
{
public:
void operator()()
{
// 一步等待任务
// 任务来了,打包成package,然后使用round robbins算法调用funcs里面的一个callback就ok了其他的不用管,如callback(package)
}
void register(callback a)
{
funcs.push_back(a);
}
private
queue<callback> funcs; //callback 可以为上面说到的异步回调函数中的任何一种,我下面用到的是
}
producer farms;
// 用户1,以及自定义的DIY函数
void task_lambda() {
// Res为DIYpackage之后返回的类型,这个根据需求定std::packaged_task<Res (package)> task([](package candy) {return candy; });
std::future<int> result = task.get_future();
while (true)
{ farms.register(task); std::cout << "task_lambda:\t" << result.get() << '\n';
}
}
// 用户2的DIY
Res f(package a)
{
return process(a);
}
void task_bind() { std::packaged_task<Res(package)> task(std::bind(f, _1)); std::future<int> result = task.get_future(); while (true)
{ std::cout << "task_bind:\t" << result.get() << '\n';
}
}
//用户3的DIY
Res func(package a)
{
return process1(a);
}
void task_thread() { std::packaged_task<Res(package)> task(func); std::future<int> result = task.get_future(); while (true)
{ std::cout << "task_thread:\t" << result.get() << '\n';
}
}
// 可以开始启动工作了 int main() { boost::thread th1(boost::bind(task_lambda)); boost::thread th2(task_bind); boost::thread th3(task_thread);
th1.join();
th2.join();
th3.join();
}
甩掉代理商的感觉怎么样,简单而且容易实现,这里还用到了函数式编程的思想,从c++的标准的演变来看,感觉c++从注重语法到现在注重应用的趋势越来越明显,当然这只是为了我们能够更简单,更快捷的开发我们的程序,以上是一些小的体验和心得,欢迎大家一起沟通交流。