Qt 线程同步之 QWaitCondition

来源:互联网 发布:dnf淘宝买金币安全吗 编辑:程序博客网 时间:2024/05/21 04:22

简述

本博用 QWaitCondition 实现了线程同步中的“生产者-消费者”模式。

  • 简述
  • 详述
  • 效果图
  • 关键知识
  • 源码
    • 类的创建
    • 类的使用
    • 源码下载

详述

  • 生产者线程生产数字,存放在 vector 中。消费者线程消耗数字。
  • 生产者线程先检测 vector 中的数字的总个数是否超出规定的限制(即代码中的 NUMBER_SIZE),超过限制则生产者线程阻塞,直到消费者线程发出 numberNotFull 条件才会进行下一步。接下来消费者线程会产生一个随机数添加到 vector 尾部,并发送numberNotEmpty 条件。
  • 消费者线程先检测 vector 中的数字个数是否为 0,为0的话,消费者线程阻塞,直到生产者线程发出 numberNotEmpty 条件才会进行下一步。接下来消费者线程取出 vector 中的第一个元素,发送给主线程。并发送 numberNotFull 条件。

效果图

这里写图片描述

关键知识

理解 QWaitCondition 的重点在于理解其 wait 函数;此处一定要详细地看文档,摘录如下:

函数原型:

bool QWaitCondition::wait(QMutex *lockedMutex, unsigned long time = ULONG_MAX)

释义:

Releases the lockedMutex and waits on the wait condition. The lockedMutex must be initially locked by the calling thread. If lockedMutex is not in a locked state, the behavior is undefined. If lockedMutex is a recursive mutex, this function returns immediately. The lockedMutex will be unlocked, and the calling thread will block until either of these conditions is met:
Another thread signals it using wakeOne() or wakeAll(). This function will return true in this case.
time milliseconds has elapsed. If time is ULONG_MAX (the default), then the wait will never timeout (the event must be signalled). This function will return false if the wait timed out.
The lockedMutex will be returned to the same locked state. This function is provided to allow the atomic transition from the locked state to the wait state.

源码

类的创建

testThread.h

#pragma once#include <QThread>class ThreadConsumer : public QThread{    Q_OBJECTpublic:    ThreadConsumer(QObject *parent);    ~ThreadConsumer();    void run() Q_DECL_OVERRIDE;    bool threadStatus();    void setThreadStatus(bool status);signals:    void sendToMainWindow(const int);private:    bool m_threadStatus;};class ThreadProducer : public QThread{    Q_OBJECTpublic:    ThreadProducer(QObject *parent);    ~ThreadProducer();    void run() Q_DECL_OVERRIDE;    bool threadStatus();    void setThreadStatus(bool status);private:    bool m_threadStatus;};

testThread.cpp

#include "testThread.h"#include<QWaitCondition>#include <QMutex>#include <QVector>#include <QTime>QWaitCondition numberNotFull;QWaitCondition numberNotEmpty;QMutex mutex;QVector<int> vectInt;const int NUMBER_SIZE = 3;int generateRandomInteger(int min, int max);ThreadConsumer::ThreadConsumer(QObject *parent)    : QThread(parent){    m_threadStatus = true;}ThreadConsumer::~ThreadConsumer(){}void ThreadConsumer::run() {    while (m_threadStatus)    {        mutex.lock();        if (vectInt.isEmpty())            numberNotEmpty.wait(&mutex);        emit sendToMainWindow(vectInt.value(0));        vectInt.pop_front();        mutex.unlock();        numberNotFull.wakeAll();    }}void ThreadConsumer::setThreadStatus(bool status){    m_threadStatus = status;}bool ThreadConsumer::threadStatus(){    return m_threadStatus;}//===================================================================//类的分界线ThreadProducer::ThreadProducer(QObject *parent)    : QThread(parent){    m_threadStatus = true;}ThreadProducer::~ThreadProducer(){}void ThreadProducer::run(){    while (m_threadStatus)    {        mutex.lock();        if (vectInt.size() > NUMBER_SIZE)            numberNotFull.wait(&mutex);        mutex.unlock();        int number = generateRandomInteger(0, 1000);        mutex.lock();        vectInt.push_back(number);        mutex.unlock();        numberNotEmpty.wakeAll();        sleep(1);//避免频繁刷新界面    }}void ThreadProducer::setThreadStatus(bool status){    m_threadStatus = status;}bool ThreadProducer::threadStatus(){    return m_threadStatus;}// 生成随机数 min:随机数的最小值,max:随机数的最大值int generateRandomInteger(int min, int max){    Q_ASSERT(min < max);    // 加入随机种子。种子是当前时间距离0点0分0秒的秒数。    // 每次启动程序,只添加一次种子,以做到数字真正随机。    static bool seedStatus;    if (!seedStatus)    {        qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));        seedStatus = true;    }    int nRandom = qrand() % (max - min);    nRandom = min + nRandom;    return nRandom;}

类的使用

main.cpp

#include "testApp.h"#include <QtWidgets/QApplication>int main(int argc, char *argv[]){    QApplication a(argc, argv);    testApp w;    w.show();    return a.exec();}

testApp.h

#pragma once#include <QtWidgets/QMainWindow>#include "ui_testApp.h"class ThreadConsumer;class ThreadProducer;class testApp : public QMainWindow{    Q_OBJECTpublic:    testApp(QWidget *parent = Q_NULLPTR);    ~testApp();protected slots:    void on_btnStart_clicked();    void handleResult(const int);private:    Ui::testAppClass ui;    ThreadConsumer* thdConsumer;    ThreadProducer* thdProducer;};

testApp.cpp

#include "testApp.h"#include "testThread.h"testApp::testApp(QWidget *parent)    : QMainWindow(parent){    ui.setupUi(this);    setWindowTitle(QStringLiteral("线程同步"));    thdConsumer = new ThreadConsumer(this);    thdProducer = new ThreadProducer(this);    connect(thdConsumer, &QThread::finished, thdConsumer, &QObject::deleteLater);    connect(thdConsumer, &ThreadConsumer::sendToMainWindow, this, &testApp::handleResult);}void testApp::on_btnStart_clicked(){    thdConsumer->setThreadStatus(true);    thdConsumer->start();    thdProducer->setThreadStatus(true);    thdProducer->start();}void testApp::handleResult(const int number){    ui.lineEdit->setText(QString::number(number));}testApp::~testApp(){    thdConsumer->setThreadStatus(false);    thdConsumer->quit();    thdConsumer->wait();    thdProducer->setThreadStatus(false);    thdProducer->quit();    thdProducer->wait();}

testApp.ui
这里写图片描述

源码下载

QWaitCondition-源码下载-【站内链接】

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 车贷分期还完了怎么办 住宅70年到期后怎么办 在外地扣了12分怎么办 英语6级证书丢了怎么办 孩子腺样体肥大鼻子堵塞怎么办 孩子初中成绩太差怎么办 交违章罚单丢了怎么办 违章缴费单丢了,怎么办 违章处理单掉了怎么办 驾驶证被扣9分后怎么办 车子违章扣50分怎么办 车子扣了12分怎么办 大学把档案丢了怎么办 学校把档案丢了怎么办 高考考了200多分怎么办 高考报名号忘了怎么办 中考只考500分怎么办 档案自提了之后怎么办 冬天衣服上的毛怎么办 四维预约不上怎么办 交了订金后悔了怎么办 信而富认证失败怎么办 南京市民卡坏了怎么办 南京市民卡断了怎么办 义乌市民卡丢了怎么办 常熟市民卡丢了怎么办 昆山市民卡丢了怎么办 市民卡丢了看病怎么办 儿童市民卡丢了怎么办 眉毛纹的太黑怎么办 法院执行书下了怎么办 汽车临牌过期了怎么办 考试用了hb铅笔怎么办 处对象处的心累怎么办 孩子初中毕业考不上高中怎么办 单位停交社保后怎么办 58同城电话骚扰怎么办 回民误吃了猪肉怎么办 回族人吃了猪肉怎么办 商场倒闭了商铺怎么办 吃了金毓婷出血怎么办