说明

Qt中可以有多种使用线程的方式:

  1. 继承 QThread,重写 run() 接口;
  2. 使用 moveToThread() 方法将 QObject 子类移至线程中,内部的所有使用信号槽的槽函数均在线程中执行;
  3. 使用 QThreadPool 线程池,搭配 QRunnable
  4. 使用 QtConcurrent

本文跳过第1和第2中方式,介绍后面两种

线程池

  • 创建和销毁线程需要和OS交互,少量线程影响不大,但是线程数量太大,势必会影响性能,使用线程池可以这种开销;
  • 线程池维护一定数量的线程,使用时,将指定函数传递给线程池,线程池会在线程中执行任务;

(一)QThreadPool和QRunnable

Qt中需要继承 QRunnable,重写 run() 方法,并,将其传递给线程池 QThreadPool 进行管理

QRunnable常用接口

  1. bool QRunnable::autoDelete() const;
  2. void QRunnable::setAutoDelete(bool autoDelete);
  • QRunnable 常用函数不多,主要设置其传到底给线程池后,是否需要自动析构;
  • 若该值为false,则需要程序员手动析构,要注意内存泄漏;

QThreadPool常用接口

  1. void QThreadPool::start(QRunnable * runnable, int priority = 0);
  2. bool QThreadPool::tryStart(QRunnable * runnable);
  • start() 预定一个线程用于执行QRunnable接口,当预定的线程数量超出线程池的最大线程数后,QRunnable接口将会进入队列,等有空闲线程后,再执行;
  • priority指定优先级
  • tryStart()start() 的不同之处在于,当没有空闲线程后,不进入队列,返回false
  1. void QThreadPool::cancel(QRunnable * runnable);
  2. void QThreadPool::clear();
  1. 如果,指定的QRunnable还没有执行,则从队列中移除
  2. 清空队列中还没有执行的QRunnable;
  1. bool QThreadPool::waitForDone(int msecs = -1);
  • 等待所有线程结束并释放资源(如果需要自动释放的话);
  • msecs指定超时;
  • 若所有线程都被移除,则,返回true,否则返回false;
  1. int maxThreadCount() const
  2. void setMaxThreadCount(int maxThreadCount)
  • 线程池维护的最大线程数量;
  • 设定该值,不会影响已经开始的线程;
  • 若没有设定,默认值是最大线程数,可以用:QThread::idealThreadCount(); 获取;
  1. int expiryTimeout() const
  2. void setExpiryTimeout(int expiryTimeout)
  • 线程的终结超时;
  • 没有开启,且超过终结时间的线程,会退出,这些线程会根据需要重启开始,即这些线程不会消失,线程池会重新取出这些线程,开启或者放入队列,所谓的终结超时就是重新排列等待队列;
  • 建议在创建线程池后,调用 start() 前设定终结超时;
  1. static QThreadPool * QThreadPool::globalInstance();
  • 全局内存池实例;
  • 若创建QThreadPool实例,则在实例生存周期内,内存池有效,

代码示例

  1. //MyRunnable.h
  2. class MyRunnable : public QRunnable
  3. {
  4. public:
  5. MyRunnable(const QString& thread_name);
  6. void run();
  7. private:
  8. QString threadName;
  9. };
  1. //MyRunnable.cpp
  2. #include "myrunnable.h"
  3. MyRunnable::MyRunnable(const QString &thread_name) : threadName(thread_name){}
  4. void MyRunnable::run()
  5. {
  6. qDebug()<<"Start thread id:"<<QThread::currentThreadId();
  7. int count = 0;
  8. while(true)
  9. {
  10. if(count >= 10)
  11. {
  12. break;
  13. }
  14. qDebug()<<threadName<<" Count:"<<count++;
  15. QThread::msleep(500);
  16. }
  17. }
  1. //调用处
  2. MyRunnable* my_runnable = new MyRunnable("1# thread");
  3. my_runnable->setAutoDelete(true);
  4. MyRunnable* my_runnable_2 = new MyRunnable("2# thread");
  5. my_runnable_2->setAutoDelete(true);
  6. threadPool.start(my_runnable);
  7. threadPool.start(my_runnable_2);

(二)QtConcurrent

若有大量工作需要完成,则使用方式1、2、3均可,但是若只有一小段工作,需要在线程中完成,无论是使用QThread,还是moveToThread,更或者,使用QThreadPool,都有大材小用的感觉,这时候,使用 QtConcurrent 就是最佳选择

下面的说明,以Qt自带的例子为基础,并加入部分修改,例子目录:..\Qt\Qt5.5.1_mingw\Examples\Qt-5.5\qtconcurrent\runfunction

pro文件中添加模块

  1. QT += concurrent

代码示例:

  1. QString hello(QString name)
  2. {
  3. qDebug() << "Hello" << name << "from" << QThread::currentThread();
  4. return name;
  5. }
  1. //掉用处
  2. QFuture<QString> f1 = QtConcurrent::run(hello, QString("Alice"));
  3. QFuture<QString> f2 = QtConcurrent::run(&threadPool, hello, QString("Bob"));
  4. f1.waitForFinished();
  5. f2.waitForFinished();
  6. qDebug()<<f1.result();
  7. qDebug()<<f2.result();

输出如下:

  1. Hello "Alice" from QThread(0x1b1562a8, name = "Thread (pooled)")
  2. Hello "Bob" from QThread(0x1b156248, name = "Thread (pooled)")
  3. "Alice"
  4. "Bob"

(1)说明:

  1. QFuture<T> QtConcurrent::run(Function function, ...);
  2. //QtConcurrent::run(QThreadPool::globalInstance(), function, ...);
  3. QFuture<T> QtConcurrent::run(QThreadPool * pool, Function function, ...);

QtConcurrent::run() 方法的第一个参数是线程池,可以指定线程池,若没有指定,则使用全局线程池;

(2)执行普通函数,并传参,获取返回值

参考上例

  • 将需要传递的参数依次跟在函数名后面;
  • 使用 QFuture<T>result() 方法获取返回值;

(3)执行非const成员函数

  1. QFuture<QString> f1 = QtConcurrent::run(this, &MainWindow::Hello, QString("Alice"));
  2. QFuture<QString> f2 = QtConcurrent::run(&threadPool, this, &MainWindow::Hello, QString("Bob"));
  • 线程池和传参以及返回值相同;
  • 既然是成员,则需要指定实例,且是非const,则可能需要修改成员,在函数名前传入实例指针或者实例的应用;

(4)执行const成员

  1. // call 'QList<QByteArray> QByteArray::split(char sep) const' in a separate thread
  2. QByteArray bytearray = "hello world";
  3. QFuture<QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split, ',');
  4. ...
  5. QList<QByteArray> result = future.result();

const成员不会使用非const成员,所以,传入指针/引用或或者形参并没有区别,上例中,就是传入了形参

Qt线程池的更多相关文章

  1. QT 线程池 + TCP 小试(一)线程池的简单实现

    *免分资源链接点击打开链接http://download.csdn.net/detail/goldenhawking/4492378 很久以前做过ACE + MFC/QT 的中轻量级线程池应用,大概就 ...

  2. QT 线程池 + TCP 小试(三)实现最终功能

    *免分资源链接点击打开链接http://download.csdn.net/detail/goldenhawking/4492378 有了TCP.线程池,我们就可以把他们连接起来.使用最简单的 QMa ...

  3. C++11消息队列 + Qt线程池 + QRunnable执行任务简单模型

    1.模板类queue,包含头文件<queue>中,是一个FIFO队列. queue.push():在队列尾巴增加数据 queue.pop():移除队列头部数据 queue.font():获 ...

  4. Qt 线程池QThreadPool类、QRunnable类

    QThreadPool类 用来管理 QThreads.此类中的所有函数都是线程安全的. 主要属性: 1.activeThreadCount: 此属性表示线程池中的活动线程数,通过activeThrea ...

  5. Qt多线程-QThreadPool线程池与QRunnable

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt多线程-QThreadPool线程池与QRunnable     本文地址:https:/ ...

  6. Qt中的多线程与线程池浅析+实例

    1. Qt中的多线程与线程池 今天学习了Qt中的多线程和线程池,特写这篇博客来记录一下 2. 多线程 2.1 线程类 QThread Qt 中提供了一个线程类,通过这个类就可以创建子线程了,Qt 中一 ...

  7. Qt 学习之路 :Qt 线程相关类

    希望上一章有关事件循环的内容还没有把你绕晕.本章将重新回到有关线程的相关内容上面来.在前面的章节我们了解了有关QThread类的简单使用.不过,Qt 提供的有关线程的类可不那么简单,否则的话我们也没必 ...

  8. C#线程池用法

    C#线程池用法 在C#编程语言中,使用线程池可以并行地处理工作,当强制线程和更新进度条时,会使用内建架构的ThreadPool类,为批处理使用多核结构,这里我们来看在C#编程语言中一些关于来自Syst ...

  9. Qt 线程基础

    (转自:http://my.oschina.net/laopiao/blog/88158) 何谓线程? 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据 ...

随机推荐

  1. 软件包管理rpm和yum

    rpm的使用: 安装的包相关包信息会保存在/var/lib/rpm目录下的文件中 安装参数: -i install安装 -v 显示详细信息 -h 打印####号 -V 校验软件包,会到/var/lib ...

  2. 代码质量管理 SonarQube 系列之 安装

    简介 SonarQube 是一个开源的代码质量管理系统. 功能介绍: 15种语言的静态代码分析 Java.JavaScript.C#.TypeScript.Kotlin.Ruby.Go.Scala.F ...

  3. Xor Path 牛客,HPU--C--LCA

    题解: 题目要求求出u和v两点在最短路径上的异或和.怎么确定最短路径呢?,就是U到LCA(u,v)的路径加上V到LCA(u,v).根据异或的性质,如k^a^a=k,即异或一个值两边等于原数值. 所以维 ...

  4. 【题解】P2024 [NOI2001]食物链 - 数据结构 - 并查集

    P2024 [NOI2001]食物链 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 动物王国中有三类动物 \(A,B ...

  5. Mysql基础练习--实例

    修改字段名:alter table 表名 change 旧字段名 新字段名 新数据类型;--- 主键 ------------------------------------------------- ...

  6. pytorch seq2seq闲聊机器人

    cut_sentence.py """ 实现句子的分词 注意点: 1. 实现单个字分词 2. 实现按照词语分词 2.1 加载词典 3. 使用停用词 "" ...

  7. go获取当前项目下所有依赖包

    在设置好GOPATH,GOROOT的环境变量的情况下. 在项目配置好pkg.bin.src等这几个目录的情况,进入src目录. 在终端,输入:go get ./... 即可获得所有依赖包.

  8. Deepin15.11-mysql5.7安装与配置

    目录 1.卸载 2.换源 3.安装mysql-5.7并修改密码 4.修改mysql中字符编码 deepin系统中,默认的系统源,使用apt-get install mysql-server会自动拉取m ...

  9. ST3 package control

    view-> showconsole    (ctrl+`) import urllib.request,os,hashlib; h = 'df21e130d211cfc94d9b0905775 ...

  10. icmp的抓包分析

    ICMP(Internet Control Message Protocol)Internet控制报文协议.它是TCP/IP协议簇的一个子协议,用于在IP主机.路由器之间传递控制消息.控制消息是指网络 ...