线程

thread.h

#ifndef THREAD_H
#define THREAD_H

#include <QWidget>
#include<QThread>
class Thread : public QThread
{
    Q_OBJECT
public:
    Thread();

    void run() override;
signals:
    void notify() ;
};

#endif // THREAD_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include"thread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

public slots:
    void handle() ;
private:
    Ui::Widget *ui;
    Thread thread ;
};
#endif // WIDGET_H
	

main.cpp

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

thread.cpp

#include "thread.h"

Thread::Thread()
{

}

void Thread::run()
{
    //在新创建的线程中,qt不允许直接对界面进行修改
    //虽然不可以修改界面,但是可以针对时间来进行计时.当每到了一秒钟的时候,通过信号槽,来通知主线程,负责更新的界面内容.

            for (int i = 0; i < 10; i++)
            {
                // sleep 是 QThread 的成员函数,就可以直接调用。
                sleep(1);
                // 发送一个信号,通知主线程。
                emit notify();
            }

}

widget.cpp

#include "thread.h"

Thread::Thread()
{

}

void Thread::run()
{
    //在新创建的线程中,qt不允许直接对界面进行修改
    //虽然不可以修改界面,但是可以针对时间来进行计时.当每到了一秒钟的时候,通过信号槽,来通知主线程,负责更新的界面内容.

            for (int i = 0; i < 10; i++)
            {
                // sleep 是 QThread 的成员函数,就可以直接调用。
                sleep(1);
                // 发送一个信号,通知主线程。
                emit notify();
            }

}

在这里插入图片描述

start

线程启动

run

exec

quit

QThread 是 Qt 框架封装的线程类,提供了与 Qt 事件循环、信号槽机制深度集成的线程管理能力;而 C++11 std::thread 是标准库的基础线程类,提供更轻量、平台无关的线程操作。以下是 QThread 常用接口的用途及与 std::thread 的对比:

一、QThread 常用接口及用途

接口 用途说明 核心特性
start(Priority) 启动线程,触发 run() 函数执行(线程进入运行状态)。
Priority 可选(如 Qt::HighPriority),用于设置线程优先级。
必须显式调用(线程不会自动启动);优先级设置依赖系统支持。
run() 线程入口函数(默认实现会启动事件循环 exec()),子类可重写以定义线程任务。 若重写 run() 且未调用 exec(),线程执行完任务后会直接结束(无事件循环)。
exec() 启动线程的事件循环(仅在 run() 中调用有效),使线程可处理事件(如信号槽、定时器)。 事件循环会阻塞等待事件,直到 quit()/exit() 被调用才退出。
quit()/exit(int) quit() 等价于 exit(0),用于请求事件循环退出(异步操作)。 仅对“有事件循环的线程”有效,线程会处理完当前事件后退出。
wait(unsigned long timeout) 阻塞当前线程,等待目标线程结束(超时可选,单位毫秒)。返回 true 表示线程正常结束,false 表示超时。 支持超时等待,可多次调用(线程结束后调用立即返回 true)。
terminate() 强制终止线程(危险!不推荐使用)。 直接终止线程执行,可能导致资源泄漏、数据不一致(如文件未关闭、锁未释放)。
isRunning() 判断线程是否正在运行(run() 已启动且未结束)。 用于查询线程状态。
isFinished() 判断线程是否已结束(run() 执行完毕)。 线程结束后返回 true
currentThread() 静态方法,返回当前执行代码的线程对象指针。 类似 std::this_thread::get_id(),用于获取当前线程上下文。
moveToThread(QObject*) QObject 子类对象“移动”到线程中,使该对象的槽函数在目标线程执行(线程安全的信号槽基础)。 Qt 独特机制,实现对象与线程的绑定,避免直接操作线程的复杂性。

二、与 C++11 std::thread 的核心对比

维度 QThread std::thread
线程启动 需显式调用 start() 启动,start() 会触发 run() 执行。 构造时传入可调用对象(函数、lambda 等)即自动启动(std::thread t(func))。
入口函数 默认入口是 run()(可重写),默认实现启动事件循环 exec() 入口是构造时传入的可调用对象(无默认实现,需手动定义任务)。
事件循环 内置事件循环(exec()),支持信号槽、定时器、事件处理(Qt 核心优势)。 无内置事件循环,需手动实现(如用 std::condition_variable 模拟)。
线程同步 wait() 支持超时等待,可多次调用。 join() 无超时(必须等待线程结束),且仅能调用一次(否则抛异常);detach() 分离线程(无法再同步)。
线程安全通信 依赖 Qt 信号槽机制(跨线程信号槽自动排队,线程安全)。 需手动使用 std::mutexstd::condition_variable 等同步原语。
对象与线程绑定 提供 moveToThread() 机制,方便将对象与线程绑定(槽函数在目标线程执行)。 无类似机制,需手动确保对象在线程中安全访问(如通过互斥锁)。
优先级控制 start(Priority) 支持线程优先级设置(依赖系统)。 需通过 std::thread::native_handle() 结合平台 API(如 pthread_setschedparam)设置,无标准接口。
强制终止 提供 terminate()(不推荐)。 无标准强制终止接口,需通过自定义标志位(如 std::atomic<bool>)让线程主动退出。
适用场景 Qt 框架内的多线程开发(尤其是需与 UI 交互、依赖事件循环的场景)。 纯 C++ 项目、轻量级线程任务、无事件循环需求的场景。

三、典型使用场景对比

1. 基础线程任务
  • QThread 方式
    重写 run() 实现任务,通过 start() 启动,wait() 等待结束。

    class MyThread : public QThread {
    protected:
        void run() override {
            // 线程任务
            for (int i = 0; i < 1000000; ++i) {}
        }
    };
    // 使用
    MyThread t;
    t.start();  // 启动线程
    t.wait();   // 等待结束
    
  • std::thread 方式
    构造时传入任务函数,join() 等待结束。

    void task() {
        for (int i = 0; i < 1000000; ++i) {}
    }
    // 使用
    std::thread t(task);
    t.join();  // 等待结束(必须调用,否则程序可能崩溃)
    
2. 带事件循环的线程(仅 QThread 支持)

QThread 可通过事件循环处理信号槽、定时器等,std::thread 需手动实现:

// QThread 带事件循环的线程
class Worker : public QObject {
    Q_OBJECT
public slots:
    void doWork() { /* 处理任务 */ }
};

QThread thread;
Worker worker;
worker.moveToThread(&thread);  // 绑定对象到线程
thread.start();                // 启动线程(默认执行 exec() 进入事件循环)
QTimer::singleShot(0, &worker, &Worker::doWork);  // 向线程发送任务

c++11thread实现QThread

四、核心差异总结

  • 集成度:QThread 与 Qt 事件循环、信号槽深度绑定,适合 Qt 生态;std::thread 是标准库基础组件,更通用但需手动处理同步。
  • 易用性:QThread 提供 moveToThread()、事件循环等高级特性,简化跨线程通信;std::thread 更轻量,但需手动管理同步细节。
  • 适用场景:Qt 项目优先用 QThread(尤其是需与 UI 交互时);纯 C++ 项目或轻量级任务用 std::thread 更合适。

选择时需根据项目是否依赖 Qt 框架、是否需要事件循环机制来决定。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐