您的位置:首页 > 其它

QSemaphore 类例子

2015-10-20 14:00 218 查看
QSemaphore 能够提供类似于生产者消费者的模式,既一个生产者进行生成,另一个消费者进行消费。(在多线程中保护多个数据的一个类)

具体先看看QSemaphore 的介绍吧~

QSemaphore 它的成员函数是

[cpp] view
plaincopy

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 )

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

[cpp] view
plaincopy

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 的描述

[cpp] view
plaincopy

/// \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

[cpp] view
plaincopy

#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 对象的工作量

[cpp] view
plaincopy

///////////////// 生产者 //////////////////////////////

/// \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();

}

}

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

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

[cpp] view
plaincopy

/////////// 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个资源

}

}

例子下载

FROM: http://blog.csdn.net/qyvlik/article/details/44138343
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: