QT实现线程4种方法
- QThread:重、长生命周期、独立线程、一直跑
- moveToThread:最推荐、最安全、Qt 官方标准写法
- QRunnable+QThreadPool:轻量任务、自动销毁、线程池、不能随便发信号
- QtConcurrent:最简单、一行代码跑异步、适合批量计算

QRunnable+QThreadPool
-
任务型线程,不是线程本身
-
丢进线程池,自动分配线程
-
任务执行完 自动删除
-
优点:轻、快、省资源
-
缺点:
默认不是 QObject,不能直接发信号
不适合长周期轮询(100ms 一直跑)
QRunnable 自带的行为,不需要你手动写 delete task,没有内存泄露风险
1、把 task 加入任务队列QThreadPool
2、在线程中执行 task->run ()
3、run () 执行完 → 自动 delete task
c
#ifndef TASKRUNNABLE_H
#define TASKRUNNABLE_H
#include <QRunnable>
#include <QThreadPool>
#include <QDebug>
class TaskRunnable : public QRunnable
{
public:
// 必须声明构造函数
TaskRunnable(){}
~TaskRunnable(){
qDebug() << "~TaskRunnable called";
}
TaskRunnable(int taskId);
// 必须重写 run()
void run() override;
private:
int m_taskId;
};
#endif // TASKRUNNABLE_H
bash
#include "taskrunnable.h"
TaskRunnable::TaskRunnable(int taskId) : m_taskId(taskId)
{
}
void TaskRunnable::run()
{
qDebug() << "Running task" << m_taskId << "in thread:" << QThread::currentThreadId();
// 模拟任务执行
for (int i = 0; i < 30; ++i) {
qDebug() << "Task" << m_taskId << "step" << i;
QThread::msleep(50);
}
qDebug() << "Task" << m_taskId << "completed";
}
bash
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "taskrunnable.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QThreadPool *pool = QThreadPool::globalInstance();
qDebug() << "Max thread count:" << pool->maxThreadCount();
TaskRunnable *task = new TaskRunnable();
pool->start(task); // 任务完成后自动删除
/*
* QRunnable 自带的行为,不需要你手动写 delete task,没有内存泄露风险
1、把 task 加入任务队列QThreadPool
2、在线程中执行 task->run ()
3、run () 执行完 → 自动 delete task
*/
}
MainWindow::~MainWindow()
{
delete ui;
}
QThread
自定义QThread继承至QThread,重写run方法,子线程处理逻辑放在run方法中。
完全控制线程生命周期,适合长时间运行的任务
bash
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QThread>
#include <QDebug>
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = nullptr) : QThread(parent) {}
protected:
void run() override {
qDebug() << "Thread started:" << QThread::currentThreadId();
for (int i = 0; i < 10; ++i) {
qDebug() << "Processing in thread:" << i;
msleep(100); // 模拟工作
}
qDebug() << "Thread finished:" << QThread::currentThreadId();
}
};
#endif // MYTHREAD_H
bash
#include "mainwindow.h"
#include "mythread.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 1. 直观易懂,类似传统线程编程
// 2. 完全控制线程生命周期
// 3. 适合长时间运行的任务
// 4. 可以重写run()方法自定义行为
MyThread thread;
thread.start();
thread.wait(); // 等待线程完成
}
MainWindow::~MainWindow()
{
delete ui;
}
moveToThread
- 把一个 普通 QObject 类丢进子线程
- 所有函数、变量、槽函数 全部自动进子线程
- 信号槽安全、跨线程没问题
- 线程一直跑,不销毁
- 优点:
结构清晰
信号槽完美
长生命周期
不阻塞 UI
适合一直运行的后台任务(PLC 轮询、串口、网口)
bash
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QDebug>
#include <QThread>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
public slots:
void doWork() {
qDebug() << "Worker started in thread:" << QThread::currentThreadId();
for (int i = 0; i < 10; ++i) {
qDebug() << "Worker processing:" << i;
QThread::msleep(100);
}
emit workFinished();
}
signals:
void workFinished();
};
#endif // WORKER_H
bash
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "worker.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 使用moveToThread的方式
Worker *worker = new Worker;
QThread *workerThread = new QThread;
worker->moveToThread(workerThread);
//将线程创建后并start开启线程,发送started信号,触发子线程doWork具体处理逻辑
QObject::connect(workerThread, &QThread::started, worker, &Worker::doWork);
//子线程处理结束后发送workFinished信号,通知线程quit退出
QObject::connect(worker, &Worker::workFinished, workerThread, &QThread::quit);
//工作完成后安全删除Worker对象
QObject::connect(worker, &Worker::workFinished, worker, &QObject::deleteLater);
//线程结束后安全删除QThread对象
QObject::connect(workerThread, &QThread::finished, workerThread, &QThread::deleteLater);
workerThread->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
QtConcurrent
QT += concurrent # QtConcurrent 必须加这个模块
1、QtConcurrent::run执行具体子线程处理逻辑
2、QFutureWatcher监控子线程任务完成状态
3、QFutureWatcher链接QFutureWatcher::finished子线程结束信号进行进一步处理
bash
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
int calcFunction();
private slots:
// 任务完成后回到主线程更新UI
void onTaskFinished(int result);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
bash
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtConcurrent> // 必须包含
#include <QFuture> // 接收返回值
#include <QFutureWatcher> // 监听任务完成
#include <QThread>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 一行代码启动子线程
QFuture<int> future = QtConcurrent::run(this, &MainWindow::calcFunction);
// 监听任务完成
QFutureWatcher<int> *watcher = new QFutureWatcher<int>(this);
watcher->setFuture(future);
// 任务完成 → 自动调用槽函数(主线程安全更新UI)
connect(watcher, &QFutureWatcher<int>::finished, this, [=]() {
onTaskFinished(watcher->result());
watcher->deleteLater(); // 自动释放
});
}
MainWindow::~MainWindow()
{
delete ui;
}
int MainWindow::calcFunction()
{
qDebug() << "计算运行在线程:" << QThread::currentThread();
// 模拟耗时任务(比如读取文件、网络、计算)
QThread::msleep(1000);
return 100;
}
void MainWindow::onTaskFinished(int result)
{
qDebug() << "任务完成,结果:" << result;
}