一生一世学坛

 找回密码
 立即注册
搜索
查看: 3787|回复: 0
打印 上一主题 下一主题

QT中如何使用线程池

[复制链接]

334

主题

385

帖子

6830

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
6830
跳转到指定楼层
楼主
发表于 2021-3-4 15:44:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

创建线程需要向系统申请资源,线程切换时操作系统会切换线程上下文,可能会从用户态切换到内核态,当有很多线程时,频繁地切换线程会导致消耗大量的 CPU 以及内核资源,真正用于计算的资源就减少了,反而会降低程序的效率。线程并不是越多越好,线程池的作用是管理、复用、回收一组线程,控制线程的数量,避免频繁的创建和销毁线程而浪费资源。

Qt 中的线程池类为 QThreadPool,每一个 Qt 程序都有一个全局的线程池,调用 QThreadPool::globalInstance() 得到,它默认最多创建 8 个线程,如果想改变最大线程数则调用 setMaxThreadCount() 进行修改,调用 activeThreadCount() 查看线程池中当前活跃的线程数。

使用线程池挺简单的,定一个任务类例如叫 Task,继承 QRunnable 并实现虚函数 run(),Task 的对象作为 QThreadPool::start() 的参数就可以了,线程池会自动的在线程中调用 Task 的 run() 函数,异步执行。线程池中的 QRunnable 对象太多时并不会为立即为每一个 QRunnable 对象创建一个线程,而是让它们排队执行,同时最多有 maxThreadCount() 个线程并行执行。

提交给线程池的 QRunnable 对象在它的 run() 函数执行完后会被自动 delete 掉,如果不想线程池删除它,在调用线程池的 start() 前调用 setAutoDelete(false) 即可。

为了演示线程池的使用,下面定义一个任务类 Task,属性 id 为了便于了解任务对象的创建、执行、销毁,run() 模拟耗时操作,随机执行 [500, 2500] 毫秒,然后在 main() 函数中创建 100 个 Task 对象提交给线程池,从输出中可以看到同时只有 8 个任务在执行,run() 执行结束后任务对象被 delete 掉了。

  1. // 文件名: Task.h
  2. #ifndef TASK_H
  3. #define TASK_H

  4. #include <QRunnable>

  5. class Task : public QRunnable {
  6. public:
  7.     Task(int id);
  8.     ~Task();

  9.     void run() Q_DECL_OVERRIDE;

  10. private:
  11.     int id; // 线程的 ID
  12. };

  13. #endif // TASK_H
  14. // 文件名: Task.cpp
  15. #include "Task.h"
  16. #include <QDebug>
  17. #include <QThread>
  18. #include <QDateTime>

  19. Task::Task(int id) : id(id) {

  20. }

  21. Task::~Task() {
  22.     qDebug().noquote() << QString("~Task() with ID %1").arg(id); // 方便查看对象是否被 delete
  23. }
  24. void Task::run() {
  25.     qDebug().noquote() << QString("Start thread %1 at %2").arg(id).arg(QDateTime::currentDateTime().toString("mm:ss.z"));
  26.     QThread::msleep(500 + qrand() % 2000); // 每个 run() 函数随机执行 [55, 2500] 毫秒,模拟耗时任务
  27.     qDebug().noquote() << QString("End   thread %1 at %2").arg(id).arg(QDateTime::currentDateTime().toString("mm:ss.z"));
  28. }
  29. // 文件名: main.cpp
  30. #include <QApplication>
  31. #include <QThreadPool>
  32. #include "Task.h"

  33. int main(int argc, char *argv[]) {
  34.     QApplication a(argc, argv);

  35.     for (int i = 1; i <= 100; ++i) {
  36.         Task *task = new Task(i); // 创建任务
  37.         QThreadPool::globalInstance()->start(task); // 提交任务给线程池,在线程池中执行
  38.     }

  39.     return a.exec();
  40. }
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|分享学习  

GMT+8, 2024-5-17 10:57 , Processed in 0.043860 second(s), 8 queries , File On.

声明:本站严禁任何人以任何形式发表违法言论!

本站内容由网友原创或转载,如果侵犯了您的合法权益,请及时联系处理!© 2017 zamxqun@163.com

皖公网安备 34010402700634号

皖ICP备17017002号-1

快速回复 返回顶部 返回列表