zoukankan      html  css  js  c++  java
  • 生产者消费者

    #include <iostream>
    #include <string>
    #include <thread>
    #include <mutex>
    #include <condition_variable>
    #include <deque>
    #include <objbase.h>
    #define GUID_LEN 64
    
    using namespace std;
    
    static int kItemsToProduce = 1;
    static bool g_go_on_push_flag = true;
    static bool g_go_on_send_flag = true;
    
    std::mutex stdoutMutex;//多线程标准输出 同步锁
    
    struct FrameRepository
    {
        deque<std::string> frame_queue;   // 这里用队列代表仓库缓冲区
        int MaxSize = 10;       // 仓库所容纳的产品最大个数
        std::mutex mtx;         // 互斥量,保护产品缓冲区
        std::condition_variable repository_notFull;     // 条件变量, 指产品仓库缓冲区不为满
        std::condition_variable repository_notEmpty;    // 条件变量, 指产品仓库缓冲区不为空
    }gItemRepository;   // 产品库全局变量,生产者和消费者操作该变量.
    
    typedef struct FrameRepository FrameRepository;
    
    
    std::string generateUUID()
    {
        char buffer[GUID_LEN] = { 0 };
        GUID guid;
        if (CoCreateGuid(&guid))
        {
            fprintf(stderr, "create guid error
    ");
            return std::string();
        }
        _snprintf_s(buffer, sizeof(buffer),
            "%08X-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X",
            guid.Data1, guid.Data2, guid.Data3,
            guid.Data4[0], guid.Data4[1], guid.Data4[2],
            guid.Data4[3], guid.Data4[4], guid.Data4[5],
            guid.Data4[6], guid.Data4[7]);
        return std::string(buffer);
    }
    
    // 生产 产品
    void PushFrameItem(FrameRepository &itemRepo, std::string frame_info)
    {
        std::unique_lock<std::mutex> lock(itemRepo.mtx);
        //while (itemRepo.itemQueue.size() >= itemRepo.MaxSize) // 判断当前仓库满了
        //{
        //    {
        //        std::lock_guard<std::mutex> lock(stdoutMutex);
        //        cout << "仓库满了,生产者等待中..." << "thread id = " << std::this_thread::get_id() << endl;
        //    }
        //    itemRepo.repository_notFull.wait(lock); // 等待信号量释放锁 生产者等待"仓库缓冲区不为满"这一条件发生(将会跳出循环).
        //}
    
        itemRepo.repository_notFull.wait(lock, [&itemRepo] {
            bool full = itemRepo.frame_queue.size() >= itemRepo.MaxSize;
            if (full) {
                std::lock_guard<std::mutex> lock(stdoutMutex);
                itemRepo.frame_queue.pop_front();
    
                if (itemRepo.frame_queue.size() < itemRepo.MaxSize)
                    cout << "clear" << endl;
                cout << "仓库满了,生产者等待中..." << "thread id = " << std::this_thread::get_id() << endl;
            }
            return !full;
        });
    
        itemRepo.frame_queue.push_back(frame_info);         // 仓库放入产品
        itemRepo.repository_notEmpty.notify_all();  // 通知消费者仓库不为空
        lock.unlock();  // 释放锁
    }
    
    // 消费 产品
    std::string SendFrameItem(FrameRepository &itemRepo)
    {
        std::string frame_info;
        std::unique_lock<std::mutex> lock(itemRepo.mtx);
        //while (itemRepo.itemQueue.empty())  // 判断当前仓库空了,等待
        //{
        //    {
        //        std::lock_guard<std::mutex> lock(stdoutMutex);
        //        cout << "仓库空了,消费者等待中..." << "thread id = " << std::this_thread::get_id() << endl;
        //    }
        //    itemRepo.repository_notEmpty.wait(lock);// 消费者等待"仓库缓冲区不为空"这一条件发生.(等待信号跳出循环)
        //}
    
        // 等待信号不为空的通知,wait 第二参数为true时 向下执行,否则一直等待
        itemRepo.repository_notEmpty.wait(lock, [&itemRepo] {
            bool empty = itemRepo.frame_queue.empty();
            if (empty) {
                std::lock_guard<std::mutex> lock(stdoutMutex);
                cout << "仓库空了,消费者等待中..." << "thread id = " << std::this_thread::get_id() << endl;
            }
            return !empty;
        });
    
        frame_info = itemRepo.frame_queue.front();
        itemRepo.frame_queue.pop_front();
        itemRepo.repository_notFull.notify_all();
        lock.unlock();
        return frame_info;
    }
    
    // 生产者任务
    void PushFrameTask()
    {
        while (g_go_on_push_flag)
        {
            //std::this_thread::sleep_for(std::chrono::milliseconds(500));
    
    
            std::string uuid = generateUUID();
            if (uuid.empty())
                return;
    
            PushFrameItem(gItemRepository, uuid);    // 生产产品
            {
                std::lock_guard<std::mutex> lock(stdoutMutex);
                cout << "生产: " << kItemsToProduce << "    UUID:" << uuid << endl;
            }
            kItemsToProduce++;
        }
    }
    
    // 消费者任务
    void SendFrameTask()
    {
        static int consume_cnt = 0;
        while (true)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(20));
    
            if (!g_go_on_send_flag)
                if (consume_cnt == kItemsToProduce)
                    break;
            //this_thread::sleep_for(std::chrono::seconds(1));
            std::string item = SendFrameItem(gItemRepository);    // 消费产品
            {
                std::lock_guard<std::mutex> lock(stdoutMutex);
                cout << "消费: " << consume_cnt + 1 << "    UUID:" << item << endl;
            }
            consume_cnt++;
        }
    }
    
    int main()
    {
    
        std::thread push(PushFrameTask);
        std::thread send(SendFrameTask);
    
        push.detach();
        send.detach();
        std::this_thread::sleep_for(std::chrono::seconds(20));
        g_go_on_push_flag = false;
        g_go_on_send_flag = false;
        system("pause");
        return 0;
    }
  • 相关阅读:
    正则表达式(转)
    Collections中的shuffle()方法
    Fermat定理
    哈希算法(转)
    Hungarian method (匈牙利算法)----解决指派问题(转)
    蒙塔卡洛模拟
    线程的礼让
    线程间的沟通
    安装rlwrap
    yum切到光盘源
  • 原文地址:https://www.cnblogs.com/chinesezyc/p/9651674.html
Copyright © 2011-2022 走看看