QThread是Qt框架中位于QtCore模块下的线程管理类,为程序提供与平台无关的线程控制能力。每个QThread对象管理程序中的一个线程,线程从run()函数开始执行,默认实现会启动该线程自己的事件循环。该类继承自QObject,可以通过信号与槽在不同线程之间传递数据,是Qt编写多线程程序的基础设施。
定义
QThread是Qt框架核心模块QtCore提供的一个类,用于以平台无关的方式管理线程。一个QThread对象对应并控制程序中的一个线程,该线程从run()函数开始执行。默认情况下run()会调用exec(),从而在新建线程内部运行一个Qt事件循环[1]。
QThread继承自QObject,因此具备信号与槽机制。它提供started()和finished()等信号用于报告线程状态,并提供start()、quit()、exit()、wait()等槽与函数用于控制线程的启动与结束[2]。
在Qt的多线程技术体系中,QThread属于底层接口,位于QRunnable与QThreadPool、QtConcurrent等更高层封装之下,是其他线程工具的基础[3]。
原理
QThread的设计要点在于对象与其所管理的线程并不在同一线程中。创建QThread实例的线程被称为旧线程,而run()在新线程中执行;该实例自身仍居住于创建它的线程[4]。因此QThread的队列槽会在旧线程中执行,构造函数也在旧线程中运行,而run()在新线程中运行,若两个函数访问同一成员变量,就需要检查其线程安全性[2]。
让代码运行在新线程中有两种方式。一种是把工作对象通过QObject::moveToThread()移动到目标线程,其槽函数便在该线程中执行;另一种是继承QThread并重写run(),把需要并行执行的代码直接写在run()里[4]。
线程之间可以通过信号与槽通信。跨线程连接依赖队列连接机制,信号发出时槽函数不会立即被调用,而是等到接收者所属线程的事件循环获得控制权时才执行,从而保证槽在接收对象所在的线程中运行。
每个QThread都可以拥有自己的事件循环。初始线程通过QCoreApplication::exec()启动事件循环,其他线程则通过QThread::exec()启动,并用exit()或quit()结束。事件循环的存在使线程可以使用QTimer、QTcpSocket等依赖事件循环的非图形界面类,也使得跨线程的信号槽连接成为可能。
发展历程
Qt 3时代,Qt库可以选择不带线程支持进行构建。到Qt 4,线程支持成为始终启用的特性,同时QThread改为继承QObject,并能为每个线程提供事件循环,信号与槽机制也开始用于线程间通信。
Qt 4还引入了QReadWriteLock等同步类,用于区分共享数据的读访问与写访问,并允许多个读取者同时访问;隐式共享类也改为可安全地跨线程复制。
QThread的接口后续持续扩展:线程优先级相关函数自Qt 4.1起提供,eventDispatcher()与setEventDispatcher()自Qt 5.0起提供,requestInterruption()与isInterruptionRequested()自Qt 5.2起提供,loopLevel()自Qt 5.5起提供,用于判断当前线程是否为该对象的isCurrentThread()则自Qt 6.8起提供[1]。
应用
QThread的典型用途是把耗时或阻塞操作放到独立线程中执行,以免主线程的事件循环被阻塞导致界面无法响应。Qt自带的Mandelbrot示例即在独立工作线程中完成分形计算,计算完毕后通过信号把结果送回主线程显示。
在网络编程中,QThread可用于与网络服务器异步通信。例如阻塞式Fortune客户端示例使用单独线程与TCP服务器交互,从而避免阻塞主线程[5]。
QThread还提供线程管理方面的辅助能力:static函数idealThreadCount()返回进程可并行运行的理想线程数;currentThread()与currentThreadId()分别返回当前线程的QThread指针和平台相关的线程标识;sleep()、msleep()、usleep()则提供秒、毫秒、微秒级、与平台无关的休眠函数[1]。
创建QThread时可以通过优先级枚举影响操作系统的调度行为,取值包括IdlePriority、LowestPriority、LowPriority、NormalPriority、HighPriority、HighestPriority、TimeCriticalPriority和InheritPriority,其中InheritPriority为默认值,表示沿用创建该线程的优先级[2]。
局限
图形界面类不能在其他线程中使用。QObject本身是可重入的,但QWidget及其所有子类不可重入,只能在主线程中使用,处理耗时操作的通行做法是把计算放进工作线程,再在主线程中显示结果。
在子类化的QThread中直接实现新槽函数容易出错,因为该实例居住于创建它的线程,其槽会在旧线程而非所管理的线程中执行,需要在新线程中调用槽的开发者应当采用工作对象方式。
线程优先级设置的效果取决于操作系统的调度策略,在不支持线程优先级的系统上,例如Linux,该设置会被忽略[6]。
强制终止线程的做法不被推荐。terminate()可能在线程代码路径的任意位置将其终止,线程没有机会清理自身或释放已持有的互斥量,因此该函数被明确标注为危险且应尽量避免使用[7]。
删除QThread对象不会停止它所管理的线程,删除仍在运行的QThread会导致程序崩溃,删除前应等待finished()信号;同样,线程中创建的对象也必须在该线程结束前全部销毁[2]。
wait()与sleep()一类函数在事件驱动的Qt框架中通常并不必要,官方建议用监听finished()信号替代wait(),用QTimer替代sleep()函数。
参见
参考资料
- QThread Class [引用日期2026-10-14]
- QThread 类 [引用日期2026-10-14]
- Multithreading-Technologien in Qt - Auf dieser Seite [引用日期2026-10-14]
- Struct QThread Copy item path - Skip to main content [引用日期2026-10-14]
- src [引用日期2026-10-14]
- softwareheritage.org 上的网页 [引用日期2026-10-14]
- softwareheritage.org 上的网页 [引用日期2026-10-14]