示例程序来自Qt5.4\Examples\Qt-5.4\corelib\threads,做出一定的注解更容易理解,详细解析推荐参考Qt手册Semaphores Example、Wait Conditions Example
1. Semaphores Example
SOURCES += semaphores.cpp
QT = core
CONFIG -= app_bundle
CONFIG += console
# install
target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/semaphores
INSTALLS += target
#include <QtCore>
#include <stdio.h>
#include <stdlib.h>
//! [0]
const int DataSize = 10;
const int BufferSize = 6;
char buffer[BufferSize];
QSemaphore freeBytes(BufferSize);
QSemaphore usedBytes;
class Producer : public QThread
{
public:
void run() Q_DECL_OVERRIDE
{
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
for (int i = 0; i < DataSize; ++i) {
freeBytes.acquire(); // -1, 用掉一个空闲字节,最大只有6个空闲字节,初始为6,如果获取失败了,那就等着消费者线程读完后释放资源
buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
qDebug("+");
usedBytes.release(); // +1, 释放了一个资源,也就是产生了一个字节数据,消费者可以读取
}
}
};
class Consumer : public QThread
{
Q_OBJECT
public:
void run() Q_DECL_OVERRIDE
{
for (int i = 0; i < DataSize; ++i)
{
usedBytes.acquire(); // -1, 获取生产者线程产生的资源,获取资源不成功,那就阻塞在这里,直到生产者产生新数据
fprintf(stdout, "%c", buffer[i % BufferSize]);
freeBytes.release(); //+1, 数据读取(消费)完毕,释放了一个空闲资源
}
fprintf(stderr, "\n");
}
signals:
void stringConsumed(const QString &text);
protected:
bool finish;
};
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Producer producer;
Consumer consumer;
producer.start();
consumer.start();
producer.wait();
consumer.wait();
return 0;
}
#include "semaphores.moc"
2.
Wait Conditions Example
QT = core
CONFIG -= moc app_bundle
CONFIG += console
SOURCES += waitconditions.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/corelib/threads/waitconditions
INSTALLS += target
#include <QtCore>
#include <stdio.h>
#include <stdlib.h>
const int DataSize = 100000;
const int BufferSize = 8192;
char buffer[BufferSize];
QWaitCondition bufferNotEmpty;
QWaitCondition bufferNotFull;
QMutex mutex;
int numUsedBytes = 0;
class Producer : public QThread
{
public:
Producer(QObject *parent = NULL) : QThread(parent)
{
}
void run() Q_DECL_OVERRIDE
{
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
for (int i = 0; i < DataSize; ++i) {
mutex.lock();
if (numUsedBytes == BufferSize)
bufferNotFull.wait(&mutex);
mutex.unlock();
buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4];
mutex.lock();
++numUsedBytes;
bufferNotEmpty.wakeAll();
mutex.unlock();
}
}
};
class Consumer : public QThread
{
Q_OBJECT
public:
Consumer(QObject *parent = NULL) : QThread(parent)
{
}
void run() Q_DECL_OVERRIDE
{
for (int i = 0; i < DataSize; ++i) {
mutex.lock();
if (numUsedBytes == 0)
bufferNotEmpty.wait(&mutex);
mutex.unlock();
fprintf(stderr, "%c", buffer[i % BufferSize]);
mutex.lock();
--numUsedBytes;
bufferNotFull.wakeAll();
mutex.unlock();
}
fprintf(stderr, "\n");
}
signals:
void stringConsumed(const QString &text);
};
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Producer producer;
Consumer consumer;
producer.start();
consumer.start();
producer.wait();
consumer.wait();
return 0;
}
#include "waitconditions.moc"