• 掷骰子的多线程应用程序2基于互斥量的线程同步(复现《Qt C++6.0》)


    说明:在复现过程中出现两点问题(1)run()函数中对m_diceValued的赋值(2)do_timeOut()函数中没有对m_seq、m_diceValued进行定义。修改后的复现程序如下所示:

    主线程

    .h

    1. #pragma once
    2. #include
    3. #include "ui_ThreadTest_one.h"
    4. #include "QtClass.h"
    5. class ThreadTest_one : public QMainWindow//主线程
    6. {
    7. Q_OBJECT
    8. private:
    9. QtClass* threadA;
    10. QTimer* timer;//新定义定时器
    11. protected:
    12. void closeEvent(QCloseEvent* event);
    13. public:
    14. ThreadTest_one(QWidget* parent = nullptr);
    15. ~ThreadTest_one();
    16. private:
    17. Ui::ThreadTest_oneClass ui;
    18. public slots:
    19. void do_threadA_started();
    20. void do_threadA_finished();
    21. void on_actThread_Run_clicked();
    22. void on_actDice_Run_clicked();
    23. void on_actThread_Quit_clicked();
    24. void on_actDict_Pause_clicked();
    25. void do_timeOut();//新增定时器槽函数
    26. };

    .cpp

    1. #include "ThreadTest_one.h"
    2. #include <QCloseEvent>
    3. #include <QThread>
    4. #include <QTimer>
    5. ThreadTest_one::ThreadTest_one(QWidget *parent)
    6. : QMainWindow(parent)
    7. {
    8. ui.setupUi(this);
    9. threadA = new QtClass(this);//创建工作线程
    10. connect(threadA, &QtClass::started, this, &ThreadTest_one::do_threadA_started);
    11. connect(threadA, &QtClass::finished, this, &ThreadTest_one::do_threadA_finished);
    12. timer = new QTimer(this);
    13. timer->setInterval(200);
    14. connect(timer, &QTimer::timeout, this, &ThreadTest_one::do_timeOut);
    15. }
    16. void ThreadTest_one::do_timeOut() {
    17. int tmpSeq = 0, tmpValue = 1;
    18. int m_diceValue;
    19. static int m_seq = 0;
    20. bool valid = threadA->readValue(&tmpSeq, &tmpValue);//地址做实参,值会改变
    21. if (valid&&(tmpSeq!=m_seq&&tmpSeq!=0)) {
    22. m_seq = tmpSeq;
    23. m_diceValue = tmpValue;
    24. QString str = QString::asprintf("第%d次投骰子,点数为:%d",m_seq,m_diceValue);
    25. ui.plainTextEdit->appendPlainText(str);
    26. }
    27. }
    28. void ThreadTest_one::do_threadA_started() {
    29. ui.statusBar->showMessage("Thread状态:thread start");
    30. ui.actThread_Run->setEnabled(false);
    31. ui.actThread_Quit->setEnabled(true);
    32. ui.actDice_Run->setEnabled(true);
    33. }
    34. void ThreadTest_one::do_threadA_finished() {
    35. ui.statusBar->showMessage("Thread状态:thread finished");
    36. ui.actThread_Run->setEnabled(true);
    37. ui.actThread_Quit->setEnabled(false);
    38. ui.actDice_Run->setEnabled(false);
    39. ui.actDict_Pause->setEnabled(false);
    40. }
    41. //按键的槽函数
    42. void ThreadTest_one::on_actThread_Run_clicked() {//要用clicked才能得到响应
    43. threadA->start();
    44. }
    45. void ThreadTest_one::on_actThread_Quit_clicked() {
    46. threadA->stopThread();
    47. }
    48. void ThreadTest_one::on_actDice_Run_clicked() {
    49. threadA->diceBegin();
    50. timer->start();
    51. ui.actDice_Run->setEnabled(false);
    52. ui.actDict_Pause->setEnabled(true);
    53. }
    54. void ThreadTest_one::on_actDict_Pause_clicked() {
    55. threadA->dicePause();
    56. timer->stop();
    57. ui.actThread_Run->setEnabled(true);
    58. ui.actDict_Pause->setEnabled(false);
    59. }
    60. //重定义事件处理函数,确保窗口关闭时线程被停止
    61. void ThreadTest_one::closeEvent(QCloseEvent* event) {
    62. if (threadA->isRunning()) {
    63. threadA->terminate();
    64. threadA->wait();
    65. }
    66. event->accept();
    67. }
    68. ThreadTest_one::~ThreadTest_one()
    69. {}

    工作线程:

    .h

    1. #pragma once
    2. #include
    3. #include
    4. class QtClass : public QThread
    5. {
    6. Q_OBJECT
    7. public:
    8. QtClass(QObject *parent);
    9. ~QtClass();
    10. private:
    11. int m_seq = 0; //掷骰子次数的序号
    12. int m_diceValue;//骰子的点数
    13. bool m_paused = true;//暂停投骰子
    14. bool m_stop = false;//停止线程
    15. QMutex mutex;//基于互斥量的线程同步,定义一个互斥量
    16. protected:
    17. void run();//线程的任务,线程的事件循环
    18. public:
    19. void diceBegin();//开始掷骰子
    20. void dicePause();//暂停投骰子
    21. void stopThread();//停止线程
    22. bool readValue(int *seq, int *diceValue);//供主线程读取数据的函数
    23. };

    .cpp

    1. #include "QtClass.h"
    2. #include<QRandomGenerator>
    3. #include<QThread>
    4. QtClass::QtClass(QObject *parent)
    5. : QThread(parent)
    6. {}
    7. void QtClass::diceBegin() {//开始掷骰子
    8. m_paused = false;
    9. }
    10. void QtClass::dicePause() {//停止掷骰子
    11. m_paused = true;
    12. }
    13. void QtClass::stopThread() {//停止线程
    14. m_stop = true;
    15. }
    16. void QtClass::run() {//run函数处理事件循环
    17. m_stop = false;
    18. m_paused = true;
    19. m_seq = 0;
    20. while (!m_stop) {
    21. if (!m_paused) {
    22. mutex.lock();//锁定互斥量
    23. m_diceValue = 0;
    24. //for(int i=0;i<5;i++)
    25. m_diceValue = QRandomGenerator::global()->bounded(1, 7);
    26. //m_diceValue = m_diceValue / 5;
    27. m_seq++;
    28. mutex.unlock();//解锁互斥量
    29. }
    30. msleep(500);
    31. }
    32. quit();//退出线程
    33. }
    34. bool QtClass::readValue(int* seq, int* diceValue) {
    35. if (mutex.tryLock(100)) {
    36. *seq = m_seq;
    37. *diceValue = m_diceValue;
    38. mutex.unlock();
    39. return true;
    40. }
    41. else
    42. return false;
    43. }
    44. QtClass::~QtClass()
    45. {}

  • 相关阅读:
    MySQL-InnoDB索引详解
    前端开发(上篇)
    前端常见的十种布局
    golang RPC包的使用和源码学习(下):tinyrpc项目源码学习
    Day07 待办事项功能页面设计
    环境影响评价期末考试题库
    python+vue+django医院健康体检预约系统697vf
    9.25day5---Qt
    github新手用法详解
    mysql buffer pool详解
  • 原文地址:https://blog.csdn.net/black_procedure/article/details/133030083