3. 使用QThreadPool执行任务
任务目标
本案例演示如何通过QRunnable与QThreadPool在Qt中执行并发任务。你将创建一个继承自QRunnable的任务类,重写其run()方法,并使用QThreadPool::start()提交多个任务到线程池执行,从而避免为每个短任务单独创建线程的开销。
环境依赖
需要Qt 5.10或更高版本(使用QThreadPool::start(QRunnable*, int priority)重载),以及支持C++11的编译器。在项目文件(.pro)中确保包含:
QT += core
CONFIG += c++11
关键完整代码
以下代码创建了一个简单的QRunnable子类,每个任务输出其编号与执行线程ID,并在main()中通过线程池提交8个任务:
#include <QCoreApplication>
#include <QThreadPool>
#include <QRunnable>
#include <QThread>
#include <QDebug>
class Task : public QRunnable {
public:
explicit Task(int id) : m_id(id) {
// 任务执行完毕后自动删除该对象
setAutoDelete(true);
}
void run() override {
qInfo() << "任务" << m_id << "开始于线程:"
<< QThread::currentThreadId();
// 模拟耗时操作
QThread::msleep(50);
qInfo() << "任务" << m_id << "结束于线程:"
<< QThread::currentThreadId();
}
private:
int m_id;
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QThreadPool *pool = QThreadPool::globalInstance();
qInfo() << "最大线程数:" << pool->maxThreadCount();
// 提交8个任务到全局线程池
for (int i = 1; i <= 8; ++i) {
Task *task = new Task(i);
pool->start(task);
}
// 等待所有任务完成(阻塞直到队列清空)
pool->waitForDone();
qInfo() << "所有任务已完成";
return 0;
}
运行与验证
编译运行:
qmake
make
./threadpool_demo
验证方法:程序启动后,观察控制台输出。预期看到8个任务均被执行,且每个任务输出其开始与结束的线程ID。由于线程池默认最大线程数通常等于CPU核心数,多个任务会并发运行在不同线程上,因此不同任务的线程ID可能相同(当任务数大于线程数时,后续任务会等待空闲线程)。
通过条件:所有8个任务均打印了“开始”与“结束”日志,且程序在打印“所有任务已完成”后正常退出,无崩溃或死锁。
关键说明
setAutoDelete(true)使线程池在任务执行完毕后自动删除Task对象,因此使用new创建任务后无需手动管理内存。waitForDone()阻塞主线程直到所有已提交任务执行完毕,确保主线程退出前任务全部完成。- 若需限制并发数,可通过
pool->setMaxThreadCount(n)设置;本例使用全局线程池默认配置。