生产者与消费者模型

目录

一、生产者与消费者模型简介

二、生产者与消费者模型的实现

1.具有多个生产者&消费者线程

2.具备线程安全的缓冲区

3.线程安全的缓冲区(队列)的实现

​​​​​​​​​​​​​​3.1基于阻塞队列、互斥锁、条件变量的实现

3.2基于环形队列、信号量的实现

三、代码实现

1.基于阻塞队列、互斥锁,条件变量的实现

2.基于环形队列、信号量的实现


一、生产者与消费者模型简介

生产者与消费者模型:是一种设计模式。

        设计模式:针对典型的应用场景设计的解决方案。

        应用场景:具有资源的产生与处理的场景。

优点:

        1)解耦合

        生产者与消费者通过缓冲区通信,不再是直接通信,降低耦合度。

        2)支持忙闲不均

        一定程度解决一方过闲,一方过忙的问题。

        3)支持并发(缓冲区必须线程安全)

        多线程处理。

二、生产者与消费者模型的实现

1.具有多个生产者&消费者线程

2.具备线程安全的缓冲区

        线程安全:

        生产者与生产者的关系:互斥

        生产者与消费者的关系:同步 + 互斥

        消费者与消费者的关系:互斥

实现关键:

        创建一个线程安全的缓冲区,然后创建生产者与消费者

3.线程安全的缓冲区(队列)的实现

​​​​​​​​​​​​​​3.1基于阻塞队列、互斥锁、条件变量的实现

template <class T>
class BlockQueue {
    private:
        int _capacity;
        std::queue<T> _queue;
        pthread_mutex_t _mutex;
        pthread_cond_t _cond_pro;
        pthread_cond_t _cond_con;
    public:
        BlockQueue();
        ~BlockQueue();
        bool Push(const T &data);
        bool Pop(T *data);
};

3.2基于环形队列、信号量的实现

template <class T>
class CircularQueue {
    pricate:
        //实现环形队列
        std::vector<T> _array;
        int _capacity;
        int _front = 0;
        int _rear = 0;
 
        //实现同步
        sem_t _sem_idle;//对队列空闲空间计数
        sem_t _sem_data;//对有效数据节点计数
 
        //实现互斥
        sem_t _sem_lock;//实现互斥锁
};

三、代码实现

1.基于阻塞队列、互斥锁,条件变量的实现

#include<iostream>
#include<cstdlib>
#include<unistd.h>
#include<pthread.h>
#include<queue>

#define MAX_QUEUE 5
#define PRODUCER 4
#define CONSUMER 4

template <class T>
class BlockQueue{
  private:
    int _capacity;//缓冲区容量
    std::queue<T> _queue;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond_pro;
    pthread_cond_t _cond_con;


  public:
    BlockQueue(int cap = MAX_QUEUE) : _capacity(cap) {
      pthread_mutex_init(&_mutex, NULL);
      pthread_cond_init(&_cond_pro, NULL);
      pthread_cond_init(&_cond_con, NULL);
    }
    ~BlockQueue() {
      pthread_mutex_destroy(&_mutex);
      pthread_cond_destroy(&_cond_pro);
      pthread_cond_destroy(&_cond_con);

    }

    bool Push(const T &data) {
      pthread_mutex_lock(&_mutex);
      while (_queue.size() == _capacity) {
        pthread_cond_wait(&_cond_pro, &_mutex);
      }
      _queue.push(data);
      pthread_cond_signal(&_cond_con);
      pthread_mutex_unlock(&_mutex);
    }

    bool Pop(T *data) {
      pthread_mutex_lock(&_mutex);
      while (_queue.empty()) {
        pthread_cond_wait(&_cond_con, &_mutex);
      }
      *data = _queue.front();
      _queue.pop();
      pthread_cond_signal(&_cond_pro);
      pthread_mutex_unlock(&_mutex);
    }
};


void *Consumer(void *arg) {
  BlockQueue<int> *p = (BlockQueue<int>*)arg;
  while (1) {
    int data;
    p -> Pop(&data);
    printf("Consumer get data: %d\n", data);
  }
}

void *Producer(void *arg) {
  BlockQueue<int> *p = (BlockQueue<int>*)arg;
  int data = 1;
  while (1) {
    p -> Push(data);
    printf("Producer put data: %d\n", data);
    ++data;
  }
}


void Test() {
  int ret;
  pthread_t con_tid[CONSUMER], pro_tid[PRODUCER];

  BlockQueue<int> q;
  //Create consumer threads 
  for (int i = 0; i < CONSUMER;  ++i) {
    pthread_create(&con_tid[i], NULL, Consumer, (void*)&q);
    if (ret != 0) {
      std::cout<<"Create consumer threads error!"<<std::endl;
      return;
    }
  }

  //Create producer threads 
  for (int i = 0; i < PRODUCER;  ++i) {
    pthread_create(&pro_tid[i], NULL, Producer, (void*)&q);
    if (ret != 0) {
      std::cout<<"Create producer threads error!"<<std::endl;
      return ;
    }
  }

  //wait threads 
  for (int i = 0; i < CONSUMER; ++i) {
    pthread_join(con_tid[i], NULL);
  }
  for (int i = 0; i < PRODUCER; ++i) {
    pthread_join(pro_tid[i], NULL);
  }

}

int main() {
  Test();
  return 0;
}

实现效果:

2.基于环形队列、信号量的实现

基于线程安全的环形队列、信号量,实现生产者与消费者模型。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 下面是一个使用 Qt 线程池实现生产者消费者模型的简单示例: ```cpp #include <QtCore> #include <iostream> class Producer : public QObject { Q_OBJECT public: Producer(QThreadPool *pool, QMutex *mutex, QWaitCondition *cond, QList<int> *data) : m_pool(pool), m_mutex(mutex), m_cond(cond), m_data(data) { m_count = 0; } public slots: void produce() { int num = qrand() % 100; QRunnable *task = new Task(num, m_mutex, m_cond, m_data); m_pool->start(task); m_count++; std::cout << "Produced " << num << std::endl; m_cond->wakeAll(); } int count() const { return m_count; } private: QThreadPool *m_pool; QMutex *m_mutex; QWaitCondition *m_cond; QList<int> *m_data; int m_count; }; class Consumer : public QObject { Q_OBJECT public: Consumer(QMutex *mutex, QWaitCondition *cond, QList<int> *data) : m_mutex(mutex), m_cond(cond), m_data(data) { } public slots: void consume() { m_mutex->lock(); while (m_data->isEmpty()) { m_cond->wait(m_mutex); } int num = m_data->takeFirst(); std::cout << "Consumed " << num << std::endl; m_mutex->unlock(); } private: QMutex *m_mutex; QWaitCondition *m_cond; QList<int> *m_data; }; class Task : public QRunnable { public: Task(int num, QMutex *mutex, QWaitCondition *cond, QList<int> *data) : m_num(num), m_mutex(mutex), m_cond(cond), m_data(data) { } void run() { m_mutex->lock(); while (m_data->size() >= 10) { m_cond->wait(m_mutex); } m_data->append(m_num); m_mutex->unlock(); } private: int m_num; QMutex *m_mutex; QWaitCondition *m_cond; QList<int> *m_data; }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); qsrand(QTime::currentTime().msec()); QThreadPool pool; pool.setMaxThreadCount(5); QMutex mutex; QWaitCondition cond; QList<int> data; Producer producer(&pool, &mutex, &cond, &data); Consumer consumer(&mutex, &cond, &data); QObject::connect(&producer, &Producer::produce, &consumer, &Consumer::consume); QTimer timer; QObject::connect(&timer, &QTimer::timeout, &producer, &Producer::produce); timer.start(1000); QTimer countTimer; QObject::connect(&countTimer, &QTimer::timeout, [&producer]() { std::cout << "Produced " << producer.count() << " items" << std::endl; }); countTimer.start(5000); return app.exec(); } ``` 在上面的示例中,`Producer` 和 `Consumer` 类继承自 `QObject`,并使用 Qt 信号和槽机制进行通信。`Producer` 类的 `produce()` ### 回答2: Qt线程池可以很好地实现生产者消费者模型生产者消费者模型主要是通过一个共享的缓冲区来实现生产者生产数据,消费者消费数据的过程。下面是一个使用Qt线程池实现生产者消费者模型的示例: 1. 定义一个数据结构,用于存储生产者消费者共享的数据。这个数据结构可以是一个队列或者一个列表。 2. 创建一个Qt线程池,并设置线程池的最大线程数。 3. 创建生产者线程和消费者线程,并将它们添加到线程池中。 4. 在生产者线程中,生产数据并将数据添加到共享的数据结构中。可以使用Qt的信号槽机制,在生产者线程中发送信号,将数据发送给消费者线程。 5. 在消费者线程中,从共享的数据结构中获取数据并进行消费。可以使用Qt的信号槽机制,在消费者线程中接收信号,并处理收到的数据。 6. 在主线程中,等待生产者线程和消费者线程完成工作,并关闭线程池。 通过使用Qt线程池,可以方便地管理多个线程,避免手动管理线程的创建和销毁,从而简化了生产者消费者模型的实现。此外,Qt的信号槽机制可以方便地实现线程间的通信,从而实现生产者消费者之间的数据传递。 ### 回答3: Qt是一个跨平台的C++应用程序开发框架,它提供了丰富的类库和工具,其中也包括线程池的实现。在Qt中,可以使用QThreadPool类来创建和管理线程池。 生产者消费者模型是一种常见的多线程编程模型,其中有一组线程作为生产者,负责生成数据,另一组线程作为消费者,负责处理这些数据。线程池可以很好地支持这种模型,并提供了以下步骤来实现: 1. 创建一个线程池对象:使用QThreadPool类创建一个线程池对象,设置最大线程数、线程闲置时间等属性。 2. 创建生产者线程:通过继承QRunnable类,实现自己的生产者线程类。在类中重写run()函数,在其中完成需要生产的数据的生成。 3. 创建消费者线程:同样通过继承QRunnable类,实现自己的消费者线程类。在类中重写run()函数,在其中完成对生产者生成的数据的处理。 4. 将任务添加到线程池:使用QThreadPool的start()函数将生产者消费者线程对象添加到线程池中,线程池会自动分配线程去运行这些任务。 5. 等待线程池完成任务:可以使用QThreadPool的waitForDone()函数来等待线程池中的所有任务完成,确保所有生产者消费者线程都执行完毕。 通过以上步骤,我们可以在Qt中实现简单的生产者消费者模型。线程池可以很好地管理线程的创建和销毁,提高线程利用率和系统的性能。同时,Qt的线程池也提供了一些其他的功能,比如任务优先级和取消线程等,可以根据实际需求来灵活调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hey小孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值