QSemaphore 类例子

QSemaphore 能够提供类似于生产者消费者的模式,既一个生产者进行生成,另一个消费者进行消费。(在多线程中保护多个数据的一个类)

具体先看看QSemaphore 的介绍吧~

QSemaphore 它的成员函数是

QSemaphore ( int n = 0 )//建立对象时可以给它n个资源
~QSemaphore ()
void acquire ( int n = 1 )// 这个操作一次减少n个资源,如果现有资源不到n个就会阻塞
int available () const   //返回当前可用的QSemaphore资源个数
void release ( int n = 1 )//这个操作一次增加n个资源
bool tryAcquire ( int n = 1 )//类似于acquire,但是申请不到n个资源时不会阻塞会立即返回
bool tryAcquire ( int n, int timeout )

下面举生产者-消费者例子说明


 const int DataSize = 100000;//要生产的数据个数
 const int BufferSize = 8192;//用于盛数据的缓存大小
 char buffer[BufferSize];

//要定义两个信号量,一个用于表示自由空间,一个用于表示已用空间
 QSemaphore freeBytes(BufferSize);//自由空间初始化大小当然等于缓存大小啦
 QSemaphore usedBytes;

class Producer : public QThread
 {
 public:
     void run();
 };

 void Producer::run()
 {
     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
     for (int i = 0; i < DataSize; ++i) {
         freeBytes.acquire();//申请一个自由空间,没有就阻塞
         buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
         usedBytes.release();//已用空间增加一个,有货啦!
     }
 }


class Consumer : public QThread
 {
 public:
     void run();
 };

 void Consumer::run()
 {
     for (int i = 0; i < DataSize; ++i) {
         usedBytes.acquire();
         fprintf(stderr, "%c", buffer[i % BufferSize]);
         freeBytes.release();
     }
     fprintf(stderr, "\n");
 }

int main(int argc, char *argv[])
 {
     QCoreApplication app(argc, argv);
     Producer producer;
     Consumer consumer;
     producer.start();
     consumer.start();
     producer.wait();
     consumer.wait();
     return 0;
 }


以上是一对一的模式,一般来说,生产者多于消费者或者消费者多于生产者的情况很常见(消费者为复数或者生产者为复数什么的也很常见的),接下来提供一个复数生产者单数消费者的例子吧~

==============================================

以下是SemaphoresThread 的描述

/// \author qyvlik
/// \abstract
/// \version 0.0.1
/// \date 2015/03/08
///

#ifndef SEMAPHORESTHREAD_H
#define SEMAPHORESTHREAD_H

#include <QObject>
#include <QSemaphore>
#include <QList>
#include <QThread>

 print data to the console ///
#include <QDebug>
#include <stdio.h>
 print data to the console ///

class SemaphoresThread : public QThread
{
    Q_OBJECT

public:
    explicit SemaphoresThread(QObject *parent = 0);
    ~SemaphoresThread();

protected:
    static const int BufferSize;    // 总的可被生产者使用的空间大小
    static const int DataSize;      //

    static QSemaphore freeBytes;    // 全局静态对象,在生产者中,用于累减可用来生成的资源的空间大小 ; 在消费者中,被累加.
    static QSemaphore usedBytes;    // 全局静态对象,在生产者中,用于累加可用来生成的资源的空间大小 ; 在消费者中,被累减.

    static QList<int> data;         // 全局静态数据对象

    virtual void run() = 0;

};

#endif // SEMAPHORESTHREAD_H
    static const int BufferSize;    // 总的可被生产者使用的空间大小
    static const int DataSize;      //
    static QSemaphore freeBytes;    // 全局静态对象,在生产者中,用于累减可用来生成的资源的空间大小 ; 在消费者中,被累加.
    static QSemaphore usedBytes;    // 全局静态对象,在生产者中,用于累加可用来生成的资源的空间大小 ; 在消费者中,被累减.
    static QList<int> data;         // 全局静态数据对象

====================================
我们的Producer类继承自SemaphoresThread 

#ifndef PRODUCER_H
#define PRODUCER_H

#include "SemaphoresThread.h"
#include <QMutex>

class Producer : public SemaphoresThread
{
    Q_OBJECT
public:
    explicit Producer(QObject *parent = 0);
    ~Producer();

protected:
    void run();
// static function to operator ProducerCount //
    static void addProducer();
    static void removeProducer();
    static int producerCount();

private:
    static int ProducerCount;
    static QMutex mutex;
};

#endif // PRODUCER_H

增加了两个静态对象,用于记录Producer构造的次数与构造的个数

通过构造的个数来计算每个Producer 对象的工作量

/ 生产者 //
/// \brief Producer::run
/// 通过 Producer::DataSize / Producer::producerCount() 得知每个生产者的工作量
/// 如果 Producer::producerCount() % Producer::DataSize != 0 ;将会发生运行错误!
void Producer::run()
{
    for (int i = 0; i < Producer::DataSize / Producer::producerCount(); ++i) {
        Producer::freeBytes.acquire();
        Producer::data.append(1);
        printf("%d",Producer::data.last());
        fflush(stdout);
        Producer::usedBytes.release();
    }
}

===============================================

消费者,就仅仅打印数据了

/// run ///
/// \brief Consumer::run
/// 用来消费 data 中的数据的
void Consumer::run()
{
    for (int i = 0; i < SemaphoresThread::DataSize; ++i) {
        SemaphoresThread::usedBytes.acquire();  // 这个操作一次减少1个资源,如果现有资源不到1个就会阻塞

        printf("%d",Consumer::data.at(i)+1);
        fflush(stdout);

        SemaphoresThread::freeBytes.release(); // 这个操作一次增加1个资源
    }
}

例子下载

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值