实现线程安全的UnblockQueue

目标:实现两个生产者线程产生随机数,一个消费者线程处理产生的随机数。
实现:实现三个类,分别是消费者 Customer,生产者 Productor,工具类 UnblockQueue

UnblockQueue类 (线程安全队列,没数据的时候消费者线程等待)

UnblockQueue.h

#pragma once
#include <queue>
#include <mutex>
#include <condition_variable>
template <typename T>
class UnblockQueue {
public:
    UnblockQueue()
        :m_mutex(), m_cond(), m_queue(), m_unblock(false)
    {

    }

    void Push(T item)
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_queue.push(item);
        m_cond.notify_one();
    }

    T Pop()
    {
        std::unique_lock<std::mutex> lock(m_mutex);
        while (m_queue.empty() && !m_unblock)
        {
            m_cond.wait(lock);
        }

        if (m_unblock)
        {
            m_unblock = false;
            return nullptr;
        }
        auto item = m_queue.front();
        m_queue.pop();
        return item;
    }

    size_t Size()
    {
        std::lock_guard<std::mutex> lockerGurard(m_mutex);
        return m_queue.size();
    }

    void UnblockOne()
    {
        m_unblock = true;
        std::unique_lock<std::mutex> locker(m_mutex);
        locker.unlock();
        m_cond.notify_one();
    }
private:
    UnblockQueue(const UnblockQueue<T>& queue);
    UnblockQueue& operator= (const UnblockQueue<T>& queue);

private:
    std::queue<T> m_queue;
    std::mutex m_mutex;
    std::condition_variable m_cond;
    bool m_unblock;
};

Cutomer类

comtomer.h

#pragma once
#include <QThread>
#include <QString>
#include "UnblockQueue.h"
class Customer:public QThread
{
public:
    Customer(UnblockQueue<QString>* dataQueue);
    ~Customer();
    void Stop();
    virtual void run();
private:
    UnblockQueue<QString>* m_queue;
    bool m_stop;
};

comtomer.cpp

#include "Customer.h"
#include <QDebug>
Customer::Customer(UnblockQueue<QString>* dataQueue)
    :m_stop(true), m_queue(nullptr)
{
    m_queue = dataQueue;
}

Customer::~Customer()
{
}
void Customer::Stop()
{
    m_stop = true;
    m_queue->UnblockOne();
}

void Customer::run()
{
   m_stop = false;
   while (!m_stop)
   {
      QString item = m_queue->Pop();
      qDebug() << item;
   }
   qDebug() << "customer out";
}

Productor类

Productor.h

#include "UnblockQueue.h"
class Productor : public QThread
{
public:
    Productor(QString productName,UnblockQueue<QString>* queue);
    ~Productor();
protected:
    virtual void run();
private:
    bool m_stop;
    UnblockQueue<QString>* m_queue;
    QString m_productName;
};

Productor.cpp

#include "Productor.h"
#include <random>
Productor::Productor(QString productName, UnblockQueue<QString>* queue)
    :m_stop(true), m_queue(nullptr)
{
    m_productName = productName;
    m_queue = queue;
}

Productor::~Productor()
{
}



void Productor::run()
{
    int count = 0;
    while (count < 10)
    {
        std::random_device rd;
        QString item = QString("%1--%2").arg(m_productName).arg(QString::number(rd()));
        m_queue->Push(item);
        count++;
    }
}

main.cpp

#include <QtCore/QCoreApplication>
#include "Productor.h"
#include "Customer.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    UnblockQueue<QString>* myqueue = new UnblockQueue<QString>();
    Customer customer(myqueue);
    Productor producter1("product1", myqueue);
    Productor producter2("product2", myqueue);
    customer.start();
    producter1.start();
    producter2.start();

    QThread::msleep(3000);

    customer.Stop();
    customer.wait(2000);
    if (customer.isRunning())
    {
        customer.terminate();
    }
    customer.wait();
    return a.exec();
}

这里写图片描述

猜你喜欢

转载自blog.csdn.net/writeeee/article/details/81587843