QTimer
优化方案 多线程架构 线程通信机制 线程池
解决思路
QThread2
QThread QObject
| 函数声明 | 功能说明 |
|---|---|
bool isFinished() |
判断线程是否已结束(返回 true 表示结束) |
bool isRunning() |
判断线程是否正在运行(返回 true 表示运行中) |
Priority priority() |
获取线程优先级(如 QThread::HighPriority、QThread::NormalPriority) |
void setPriority(Priority priority) |
设置线程优先级(影响操作系统调度顺序) |
void exit(int returnCode=0) |
退出线程事件循环,returnCode=0 表示成功,非 0 表示异常 |
bool wait(unsigned long time) |
阻塞当前线程,等待目标线程结束(time 为超时时间,单位:毫秒;time=ULONG_MAX 表示无限等待) |
| 槽函数声明 | 功能说明 |
|---|---|
void quit() |
等效于 exit(0),退出线程事件循环(正常退出) |
void start(Priority priority) |
启动线程,操作系统根据 priority 调度;内部自动调用 run() |
void terminate() |
强制终止线程(非安全方式,仅紧急场景使用);调用后需配合 wait() 确保线程释放资源 |
| 信号声明 | 触发时机 |
|---|---|
void finished() |
线程即将结束时发射(可用于主线程释放资源) |
void started() |
线程开始执行前发射(run() 调用前,可用于初始化) |
| 静态函数声明 | 功能说明 |
|---|---|
int idealThreadCount() |
返回系统理想线程数(通常等于 CPU 核心数,用于线程池优化) |
void msleep(unsigned long msecs) |
强制当前线程休眠 msecs 毫秒(阻塞线程执行) |
void sleep(unsigned long secs) |
强制当前线程休眠 secs 秒 |
void usleep(unsigned long usecs) |
强制当前线程休眠 usecs 微秒 |
| 保护函数声明 | 功能说明 |
|---|---|
virtual void run() |
线程任务核心函数,start() 会自动调用;需重写以实现自定义任务 |
int exec() |
进入线程事件循环(通常在 run() 中调用),等待 exit() 触发退出 |
#include <QThread>
#include <QRandomGenerator>
#include <QTime>
#include <QStringList>
class LotteryThread : public QThread {
Q_OBJECT // 必须添加,支持信号槽机制
public:
explicit LotteryThread(QObject *parent = nullptr) : QThread(parent) {}
// 线程控制接口(供主线程调用)
void LotteryBegin() { m_Paused = false; } // 开始抽奖(取消暂停)
void LotteryPause() { m_Paused = true; } // 暂停抽奖
void IsStopThread() { m_stop = true; } // 标记线程停止
signals:
// 抽奖结果信号(发送给主线程,参数:次数序号、抽奖结果)
void prizeResult(int seq, const QString &result);
protected:
// 重写 run(),实现抽奖核心逻辑
void run() override {
m_stop = false; // 初始化停止标记
m_seq = 0; // 初始化次数序号
qsrand(QTime::currentTime().msec()); // 初始化随机数种子(线程安全)
// 线程循环:未标记停止则持续运行
while (!m_stop) {
if (!m_Paused) { // 未暂停时,生成抽奖结果
// 从奖品列表中随机选择一个结果
QString temp = prizes[qrand() % prizes.size()];
m_seq++; // 次数序号自增
emit prizeResult(m_seq, temp); // 发送结果给主线程
}
msleep(500); // 线程休眠 500ms,控制抽奖频率(避免高频占用资源)
}
quit(); // 退出线程事件循环(等效于 exit(0),正常结束)
}
private:
int m_seq = 0; // 抽奖次数序号
const QStringList prizes = {"one", "two", "three", "thanks"}; // 奖品列表
bool m_Paused = true; // 暂停标记(默认暂停)
bool m_stop = false; // 停止标记(默认不停止)
};
#include <QDialog>
#include "LotteryThread.h" // 包含自定义线程类头文件
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private slots:
// 接收工作线程的抽奖结果(更新界面)
void onthreadA(int seq, const QString& Value);
// 按钮点击槽函数
void on_pushButton_clicked(); // “开始线程”按钮
void on_pushButton_4_clicked(); // “结束线程”按钮
void on_pushButton_2_clicked(); // “开始抽奖”按钮(取消暂停)
void on_pushButton_3_clicked(); // “暂停抽奖”按钮
protected:
// 重写关闭事件,确保线程安全退出
void closeEvent(QCloseEvent* event);
private:
Ui::Dialog *ui; // 界面组件对象
LotteryThread* threadA; // 抽奖工作线程实例
};
#include "Dialog.h"
#include "ui_Dialog.h"
#include <QDebug>
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::Dialog)
{
ui->setupUi(this);
// 创建抽奖线程实例(父对象为当前界面,避免内存泄漏)
threadA = new LotteryThread(this);
// 绑定线程信号与界面槽函数:线程发送的抽奖结果 → 界面更新
connect(threadA, &LotteryThread::prizeResult, this, &Dialog::onthreadA);
}
Dialog::~Dialog()
{
delete ui; // 释放界面组件
}
// 接收抽奖结果,更新界面文本框
void Dialog::onthreadA(int seq, const QString &Value)
{
// 格式化结果文本(序号+结果)
QString text = QString::asprintf("%d:", seq) + Value;
ui->textEdit->append(text); // 在文本框中追加结果
}
// “开始线程”按钮点击:启动工作线程
void Dialog::on_pushButton_clicked()
{
if (!threadA->isRunning()) { // 避免重复启动线程
threadA->start(); // 启动线程(内部调用 run())
qDebug() << "线程已启动";
}
}
// “结束线程”按钮点击:安全终止线程
void Dialog::on_pushButton_4_clicked()
{
if (threadA->isRunning()) { // 线程运行中才执行终止
threadA->IsStopThread(); // 标记线程停止
threadA->wait(); // 等待线程结束(释放资源)
qDebug() << "线程已结束";
}
}
// “开始抽奖”按钮点击:取消线程暂停(开始生成结果)
void Dialog::on_pushButton_2_clicked()
{
threadA->LotteryBegin();
qDebug() << "抽奖开始";
}
// “暂停抽奖”按钮点击:暂停线程(停止生成结果)
void Dialog::on_pushButton_3_clicked()
{
threadA->LotteryPause();
qDebug() << "抽奖暂停";
}
// 界面关闭事件:确保线程安全退出
void Dialog::closeEvent(QCloseEvent *event)
{
if (threadA->isRunning()) { // 关闭界面时,若线程仍在运行
threadA->IsStopThread(); // 标记停止
threadA->wait(); // 等待线程结束
}
event->accept(); // 允许界面关闭
}