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

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

主线程:

.h

复制代码
#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_ThreadTest_one.h"
#include "QtClass.h"

class ThreadTest_one : public QMainWindow//主线程
{
    Q_OBJECT

private:
    QtClass* threadA;
    QTimer* timer;//新定义定时器

protected:
    void closeEvent(QCloseEvent* event);


public:
    ThreadTest_one(QWidget* parent = nullptr);
    ~ThreadTest_one();

private:
    Ui::ThreadTest_oneClass ui;

public slots:
    void do_threadA_started();
    void do_threadA_finished();
   
    void on_actThread_Run_clicked();
    void on_actDice_Run_clicked();
    void on_actThread_Quit_clicked();
    void on_actDict_Pause_clicked();
    void do_timeOut();//新增定时器槽函数

};

.cpp

复制代码
#include "ThreadTest_one.h"
#include <QCloseEvent>
#include <QThread>
#include <QTimer>


ThreadTest_one::ThreadTest_one(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
    threadA = new QtClass(this);//创建工作线程
    connect(threadA, &QtClass::started, this, &ThreadTest_one::do_threadA_started);
    connect(threadA, &QtClass::finished, this, &ThreadTest_one::do_threadA_finished);
    timer = new QTimer(this);
    timer->setInterval(200);
    connect(timer, &QTimer::timeout, this, &ThreadTest_one::do_timeOut);
    
}

void ThreadTest_one::do_timeOut() {
    int tmpSeq = 0, tmpValue = 1;
    int m_diceValue;
    static int m_seq = 0;
    bool valid = threadA->readValue(&tmpSeq, &tmpValue);//地址做实参,值会改变
    if (valid&&(tmpSeq!=m_seq&&tmpSeq!=0)) {
        m_seq = tmpSeq;
        m_diceValue = tmpValue;
        QString str = QString::asprintf("第%d次投骰子,点数为:%d",m_seq,m_diceValue);
        ui.plainTextEdit->appendPlainText(str);
    }
}

void ThreadTest_one::do_threadA_started() {
  ui.statusBar->showMessage("Thread状态:thread start");
  ui.actThread_Run->setEnabled(false);
  ui.actThread_Quit->setEnabled(true);
  ui.actDice_Run->setEnabled(true);

}
void ThreadTest_one::do_threadA_finished() {
    ui.statusBar->showMessage("Thread状态:thread finished");
    ui.actThread_Run->setEnabled(true);
    ui.actThread_Quit->setEnabled(false);
    ui.actDice_Run->setEnabled(false);
    ui.actDict_Pause->setEnabled(false);
}

//按键的槽函数
void ThreadTest_one::on_actThread_Run_clicked() {//要用clicked才能得到响应
    threadA->start();
}
void ThreadTest_one::on_actThread_Quit_clicked() {
    threadA->stopThread();
}
void ThreadTest_one::on_actDice_Run_clicked() {
    threadA->diceBegin();
    timer->start();
    ui.actDice_Run->setEnabled(false);
    ui.actDict_Pause->setEnabled(true);
}
void ThreadTest_one::on_actDict_Pause_clicked() {
    threadA->dicePause();
    timer->stop();
    ui.actThread_Run->setEnabled(true);
    ui.actDict_Pause->setEnabled(false);
}

//重定义事件处理函数,确保窗口关闭时线程被停止
void ThreadTest_one::closeEvent(QCloseEvent* event) {
    if (threadA->isRunning()) {
        threadA->terminate();
        threadA->wait();
    }
    event->accept();
}

ThreadTest_one::~ThreadTest_one()
{}

工作线程:

.h

复制代码
#pragma once

#include <QThread>
#include <QMutex>

class QtClass  : public QThread
{
	Q_OBJECT

public:
	QtClass(QObject *parent);
	~QtClass();
private:
	int m_seq = 0;   //掷骰子次数的序号
	int m_diceValue;//骰子的点数
	bool m_paused = true;//暂停投骰子
	bool m_stop = false;//停止线程
	QMutex mutex;//基于互斥量的线程同步,定义一个互斥量

protected:
	void run();//线程的任务,线程的事件循环

public:
	void diceBegin();//开始掷骰子
	void dicePause();//暂停投骰子
	void stopThread();//停止线程
	bool readValue(int *seq, int *diceValue);//供主线程读取数据的函数

};

.cpp

复制代码
#include "QtClass.h"
#include<QRandomGenerator>
#include<QThread>

QtClass::QtClass(QObject *parent)
	: QThread(parent)
{}
void QtClass::diceBegin() {//开始掷骰子
	m_paused = false;
}
void QtClass::dicePause() {//停止掷骰子
	m_paused = true;
}
void QtClass::stopThread() {//停止线程
	m_stop = true;
}
void QtClass::run() {//run函数处理事件循环
	m_stop = false;
	m_paused = true;
	m_seq = 0;
	while (!m_stop) {
		if (!m_paused) {
			mutex.lock();//锁定互斥量
			m_diceValue = 0;
			//for(int i=0;i<5;i++)
			m_diceValue = QRandomGenerator::global()->bounded(1, 7);
			//m_diceValue = m_diceValue / 5;
			m_seq++;
			mutex.unlock();//解锁互斥量
		}
		msleep(500);
	}
	quit();//退出线程
}
bool QtClass::readValue(int* seq, int* diceValue) {
	if (mutex.tryLock(100)) {
		*seq = m_seq;
		*diceValue = m_diceValue;

		mutex.unlock();
		return true;
	}
	else
		return false;
}

QtClass::~QtClass()
{}
相关推荐
旖-旎3 分钟前
《LeetCode647 回文子串 || LeetCode 5 最长回文子串》
c++·算法·leetcode·动态规划·哈希算法
玖玥拾13 分钟前
C# 语言进阶(十五)C# 游戏服务端 MySQL 数据库
服务器·开发语言·网络·数据库·mysql·c#
铅笔侠_小龙虾33 分钟前
Rust 学习目录
开发语言·学习·rust
Darkwanderor42 分钟前
对Linux的进程控制的研究
linux·运维·c++
云泽8081 小时前
从零吃透 C++ 异常:抛出捕获、栈展开、异常重抛与编码规范详解
开发语言·c++·代码规范
灯澜忆梦1 小时前
GO---可见性规则
开发语言·golang
REDcker1 小时前
libdatachannel 快速入门
c++·webrtc·datachannel
逝水无殇1 小时前
C# 文件的输入与输出详解
开发语言·数据库·后端·c#
这是个栗子2 小时前
前端开发中的常用工具函数(八)
开发语言·前端·javascript
凤凰院凶涛QAQ2 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构