程序结果:
![](https://img-blog.csdnimg.cn/img_convert/46b85f4e097a9048f9652044ed0c95b9.png)
创建Widget工程
工程文件截图,
![](https://img-blog.csdnimg.cn/img_convert/7ceccc6bc059d8c1c212718d132dcc17.png)
MultiThread001.pro如下,
#-------------------------------------------------
#
# Project created by QtCreator 2023-03-08T16:29:33
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = MultiThread001
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++11
SOURCES += \
executor.cpp \
main.cpp \
thread.cpp \
widget.cpp
HEADERS += \
executor.h \
irunable.h \
thread.h \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
添加线程类thread继承自QThread
thread.h
#ifndef THREAD_H
#define THREAD_H
#include <QThread>
#include <atomic>
#include <QMutex>
#include <QWaitCondition>
class Thread : public QThread
{
Q_OBJECT
public:
Thread(QObject *parent = nullptr);
~Thread() override;
enum State
{
Stoped,
Running,
Paused
};
State state() const;
public slots:
void start(Priority pri = InheritPriority);
void stop();
void pause();
void resume();
protected:
virtual void run() override final;
virtual void process() = 0;
private:
std::atomic_bool pauseFlag;
std::atomic_bool stopFlag;
QMutex mutex;
QWaitCondition condition;
};
#endif // THREAD_H
thread.cpp
#include "thread.h"
#include <QDebug>
Thread::Thread(QObject *parent)
: QThread(parent),
pauseFlag(false),
stopFlag(false)
{
}
Thread::~Thread()
{
stop();
}
Thread::State Thread::state() const
{
State s = Stoped;
if (!QThread::isRunning())
{
s = Stoped;
}
else if (QThread::isRunning() && pauseFlag)
{
s = Paused;
}
else if (QThread::isRunning() && (!pauseFlag))
{
s = Running;
}
return s;
}
void Thread::start(Priority pri)
{
QThread::start(pri);
}
void Thread::stop()
{
if (QThread::isRunning())
{
stopFlag = true;
condition.wakeAll();
QThread::quit();
QThread::wait();
}
}
void Thread::pause()
{
if (QThread::isRunning())
{
pauseFlag = true;
}
}
void Thread::resume()
{
if (QThread::isRunning())
{
pauseFlag = false;
condition.wakeAll();
}
}
void Thread::run()
{
qDebug() << "enter thread : " << QThread::currentThreadId();
while (!stopFlag)
{
process();
if (pauseFlag)
{
qDebug() << "Receive Pause signal! pause the thread";
mutex.lock();
condition.wait(&mutex);
mutex.unlock();
}
}
pauseFlag = false;
stopFlag = false;
qDebug() << "exit thread : " << QThread::currentThreadId();
}
添加执行器类Executor,继承自Thread
executor.h
#ifndef EXECUTOR_H
#define EXECUTOR_H
#include "thread.h"
#include "irunable.h"
class Executor : public Thread
{
public:
Executor(QObject* parent = nullptr);
~Executor() override;
void addRunable(IRunable* able);
void addRunables(const QList<IRunable*>& ables);
QList<IRunable*> getRunables();
void setStartupDelay(int ms);
void setIntervalDelay(int ms);
void start(Priority pri = InheritPriority);
protected:
virtual void process() override;
private:
QList<IRunable*> runableList;
int startupDelay;
int intervalDelay;
};
#endif // EXECUTOR_H
executor.cpp
#include "executor.h"
#include <QTimer>
#include <QEventLoop>
Executor::Executor(QObject *parent)
: Thread(parent),
startupDelay(0),
intervalDelay(0)
{
}
Executor::~Executor()
{
Thread::stop();
}
void Executor::addRunable(IRunable *able)
{
runableList.append(able);
}
void Executor::addRunables(const QList<IRunable *> &ables)
{
runableList.append(ables);
}
QList<IRunable *> Executor::getRunables()
{
return runableList;
}
void Executor::setStartupDelay(int ms)
{
startupDelay = ms;
}
void Executor::setIntervalDelay(int ms)
{
intervalDelay = ms;
}
void Executor::start(QThread::Priority pri)
{
if (startupDelay != 0)
{
QTimer::singleShot(startupDelay, this, [=]
{
Thread::start(pri);
});
}
else
{
Thread::start(pri);
}
}
void Executor::process()
{
foreach (auto able, runableList)
{
able->exec();
}
if (intervalDelay != 0)
{
QTimer::singleShot(intervalDelay, this, [=]
{
Thread::resume();
});
Thread::pause();
}
}
irunable.h
#ifndef IRUNABLE_H
#define IRUNABLE_H
class IRunable
{
public:
virtual ~IRunable() {}
virtual void exec() = 0;
};
#endif // IRUNABLE_H
主界面程序
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "executor.h"
namespace Ui {
class Widget;
}
class Executor;
class IRunable;
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButtonStart_clicked();
void on_pushButtonStop_clicked();
void on_pushButtonPause_clicked();
void on_pushButtonResume_clicked();
void on_pushButtonStatus_clicked();
void showThreadMessage(QString strMessage);
private:
Ui::Widget *ui;
Executor* executor;
QList<IRunable*> runableList;
};
class Task1 : public QObject,public IRunable
{
Q_OBJECT
public:
virtual void exec() override;
signals:
void showTaskMessage(QString strMessage);
};
class Task2 : public QObject, public IRunable
{
Q_OBJECT
public:
virtual void exec() override;
signals:
void showTaskMessage(QString strMessage);
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include "Executor.h"
#include "IRunable.h"
#include <windows.h>
void Task1 ::exec()
{
//qDebug() << "do Task1...";
emit showTaskMessage("do Task1...");
Sleep(500);
}
void Task2 ::exec()
{
//qDebug() << "do Task2...";
emit showTaskMessage("do Task2...");
Sleep(500);
}
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
executor = new Executor();
//executor->setStartupDelay(1000);
//executor->setIntervalDelay(1000);
Task1* pTask1 = new Task1();
Task2* pTask2 = new Task2();
runableList.append(pTask1);
runableList.append(pTask2);
executor->addRunables(runableList);
connect(pTask1, SIGNAL(showTaskMessage(QString)), this,SLOT(showThreadMessage(QString)));
connect(pTask2, SIGNAL(showTaskMessage(QString)), this,SLOT(showThreadMessage(QString)));
}
void Widget::showThreadMessage(QString strMessage)
{
ui->textEdit->append(strMessage);
}
Widget::~Widget()
{
delete executor;
executor = nullptr;
qDeleteAll(runableList);
runableList.clear();
delete ui;
}
void Widget::on_pushButtonStart_clicked()
{
ui->textEdit->append("Thread start");
executor->start();
}
void Widget::on_pushButtonStop_clicked()
{
ui->textEdit->append("Thread stop");
executor->stop();
}
void Widget::on_pushButtonPause_clicked()
{
ui->textEdit->append("Thread Pause");
executor->pause();
}
void Widget::on_pushButtonResume_clicked()
{
ui->textEdit->append("Thread resume");
executor->resume();
}
void Widget::on_pushButtonStatus_clicked()
{
ui->textEdit->append("Thread status");
Thread::State s = executor->state();
if (s == Thread::Stoped)
{
//qDebug() << "state : Stoped";
showThreadMessage("state : Stoped");
}
else if (s == Thread::Running)
{
//qDebug() << "state : Running";
showThreadMessage("state : Running");
}
else if (s == Thread::Paused)
{
//qDebug() << "state : Paused";
showThreadMessage("state : Paused");
}
}