c++ 简单的生产者消费者模式

        生产者消费者模型并不属于面向对象的23种设计模式之一,实际上是结构化编程思想中的一种经典模式,使用非常广泛。而在面向对象编程过程中也不会只是面向对象,通常是与结构化编程相辅相成的。好了闲话不多说,下面的例子非常简单的使用了std::thread来实现一个生产者消费者模型。

#include <iostream>
#include <thread>
#include <chrono>
#include <queue>
#include <mutex>


class worker{
public:
    worker()=delete;//禁用默认构造
    worker& operator=(const worker&)=delete;//禁用赋值
    worker& operator=(worker&&)=delete;//禁用右值赋值
    explicit worker(bool _v):m_stop_generate(_v),m_stop_consume(_v){
        std::cout<<"worker constructor called, thread id: "<<std::this_thread::get_id()<<std::endl;
        std::cout<<"对象地址: "<<this<<std::endl;
    }
    worker(const worker& wkr):m_stop_generate(wkr.m_stop_generate),m_stop_consume(wkr.m_stop_consume){
        std::cout<<"worker copy-constructor called, thread id: "<<std::this_thread::get_id()<<std::endl;
        std::cout<<"对象地址: "<<this<<std::endl;
    }
    worker(worker&& wkr){
        /*if wkr has other non-static member variables, init or clear them here*/
        m_stop_generate = wkr.m_stop_generate;
        m_stop_consume = wkr.m_stop_consume;

        wkr.m_stop_generate = false;
        wkr.m_stop_consume = false;

        std::cout<<"worker move-constructor called, thread id: "<<std::this_thread::get_id()<<std::endl;
        std::cout<<"对象地址: "<<this<<std::endl;
    }

    void stop_working(){
        //std::lock_guard<std::mutex> lock(mu);
        m_stop_generate = true;
        m_stop_consume = true;
        std::cout<<"stop called."<<std::endl;
    }

    void generate_data()const{
        while(!m_stop_generate){

            int v = 1;
            {
                std::lock_guard<std::mutex> lock(mu);
                msgQueue.push(v);
            }

            std::cout<<"生产者存值, value is: "<<v<<std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(50));//50 ms
        }
        std::cout<<"生产者线程退出。 "<<std::endl;
    }

    void consume_data()const{
        while(!m_stop_consume){
            int v;
            bool ok;
            {
                std::lock_guard<std::mutex> lock(mu);
                ok = msgQueue.empty();
                if(!ok){
                    v = msgQueue.front();
                    msgQueue.pop();
                }
            }
            if(!ok)
                std::cout<<"消费者取值 ,value is: "<<v<<std::endl;
            else
                std::cout<<"消费者等待..."<<std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(50));//50 ms
        }
        std::cout<<"消费者线程退出。 "<<std::endl;
    }

    ~worker(){
        std::cout<<"worker de-constructor called, thread id: "<<std::this_thread::get_id()<<std::endl;
        std::cout<<"对象地址: "<<this<<std::endl;
    }

public:
    int m_test_value;

private:
    static std::queue<int> msgQueue;//线程共享资源
    static std::mutex mu;//线程共享资源
    bool m_stop_generate;
    bool m_stop_consume;
};

std::queue<int> worker::msgQueue;
std::mutex worker::mu;



void dowork_nonconst(worker &a){
    std::cout<<"nonconst adress is: "<<&a<<", value is: "<<a.m_test_value<<std::endl;
}

void dowork_const(const worker &a){
    std::cout<<"const adress is: "<<&a<<", value is: "<<a.m_test_value<<std::endl;
}

int main(int argc, char *argv[])
{
    worker A(false);
    //thread的构造函数会为所有的参数制作一个匿名副本,放入其私有栈底,
    //即便可调用对象接收参数用的是引用,它也会先制作副本,再用副本去初始化可调用对象的形参,
    //虽然副本在主线程创建,但是所有权归子线程,子线程结束时会自动出栈,回收内存。
    //这样做主要是担心传入线程的局部变量,在子线程未返回前就生命周期终止,引发未定义行为。缺点是主线程失去对象控制权

    //而这些只是做了一定的防范措施,但是程序员依然可以绕过这些防范机制,比如传指针
    //或者强制指定传引用(用std::ref),这些情况下要格外关注变量的生命周期。
    //thread th(dowork_nonconst,std::ref(A));

    //thread th(dowork_const,worker(10));
    //thread th(dowork_const,A);

    //成员函数作为线程入口
    //thread th(&worker::generate_data,A);   //相对安全,因为会调用A的拷贝构造函数,缺点是主线程失去对象的控制权。
    std::thread th(&worker::generate_data,&A);   // 不安全,A可能在线程返回前就消亡了,优点是主线程可以借此控制子线程行为。
    std::thread th2(&worker::consume_data,&A);


    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    A.stop_working();

    th.join();
    th2.join();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值