Qt线程池
说明
Qt中可以有多种使用线程的方式:
- 继承 QThread,重写 run() 接口;
- 使用 moveToThread() 方法将 QObject 子类移至线程中,内部的所有使用信号槽的槽函数均在线程中执行;
- 使用 QThreadPool 线程池,搭配 QRunnable;
- 使用 QtConcurrent;
本文跳过第1和第2中方式,介绍后面两种
线程池
- 创建和销毁线程需要和OS交互,少量线程影响不大,但是线程数量太大,势必会影响性能,使用线程池可以这种开销;
- 线程池维护一定数量的线程,使用时,将指定函数传递给线程池,线程池会在线程中执行任务;
(一)QThreadPool和QRunnable
Qt中需要继承 QRunnable,重写 run() 方法,并,将其传递给线程池 QThreadPool 进行管理
QRunnable常用接口
bool QRunnable::autoDelete() const;
void QRunnable::setAutoDelete(bool autoDelete);
- QRunnable 常用函数不多,主要设置其传到底给线程池后,是否需要自动析构;
- 若该值为false,则需要程序员手动析构,要注意内存泄漏;
QThreadPool常用接口
void QThreadPool::start(QRunnable * runnable, int priority = 0);
bool QThreadPool::tryStart(QRunnable * runnable);
- start() 预定一个线程用于执行QRunnable接口,当预定的线程数量超出线程池的最大线程数后,QRunnable接口将会进入队列,等有空闲线程后,再执行;
- priority指定优先级
- tryStart() 和 start() 的不同之处在于,当没有空闲线程后,不进入队列,返回false
void QThreadPool::cancel(QRunnable * runnable);
void QThreadPool::clear();
- 如果,指定的QRunnable还没有执行,则从队列中移除
- 清空队列中还没有执行的QRunnable;
bool QThreadPool::waitForDone(int msecs = -1);
- 等待所有线程结束并释放资源(如果需要自动释放的话);
- msecs指定超时;
- 若所有线程都被移除,则,返回true,否则返回false;
int maxThreadCount() const
void setMaxThreadCount(int maxThreadCount)
- 线程池维护的最大线程数量;
- 设定该值,不会影响已经开始的线程;
- 若没有设定,默认值是最大线程数,可以用:
QThread::idealThreadCount();获取;
int expiryTimeout() const
void setExpiryTimeout(int expiryTimeout)
- 线程的终结超时;
- 没有开启,且超过终结时间的线程,会退出,这些线程会根据需要重启开始,即这些线程不会消失,线程池会重新取出这些线程,开启或者放入队列,所谓的终结超时就是重新排列等待队列;
- 建议在创建线程池后,调用 start() 前设定终结超时;
static QThreadPool * QThreadPool::globalInstance();
- 全局内存池实例;
- 若创建QThreadPool实例,则在实例生存周期内,内存池有效,
代码示例
//MyRunnable.h
class MyRunnable : public QRunnable
{
public:
MyRunnable(const QString& thread_name);
void run();
private:
QString threadName;
};
//MyRunnable.cpp
#include "myrunnable.h"
MyRunnable::MyRunnable(const QString &thread_name) : threadName(thread_name){}
void MyRunnable::run()
{
qDebug()<<"Start thread id:"<<QThread::currentThreadId();
int count = 0;
while(true)
{
if(count >= 10)
{
break;
}
qDebug()<<threadName<<" Count:"<<count++;
QThread::msleep(500);
}
}
//调用处
MyRunnable* my_runnable = new MyRunnable("1# thread");
my_runnable->setAutoDelete(true);
MyRunnable* my_runnable_2 = new MyRunnable("2# thread");
my_runnable_2->setAutoDelete(true);
threadPool.start(my_runnable);
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文件中添加模块
QT += concurrent
代码示例:
QString hello(QString name)
{
qDebug() << "Hello" << name << "from" << QThread::currentThread();
return name;
}
//掉用处
QFuture<QString> f1 = QtConcurrent::run(hello, QString("Alice"));
QFuture<QString> f2 = QtConcurrent::run(&threadPool, hello, QString("Bob"));
f1.waitForFinished();
f2.waitForFinished();
qDebug()<<f1.result();
qDebug()<<f2.result();
输出如下:
Hello "Alice" from QThread(0x1b1562a8, name = "Thread (pooled)")
Hello "Bob" from QThread(0x1b156248, name = "Thread (pooled)")
"Alice"
"Bob"
(1)说明:
QFuture<T> QtConcurrent::run(Function function, ...);
//QtConcurrent::run(QThreadPool::globalInstance(), function, ...);
QFuture<T> QtConcurrent::run(QThreadPool * pool, Function function, ...);
QtConcurrent::run() 方法的第一个参数是线程池,可以指定线程池,若没有指定,则使用全局线程池;
(2)执行普通函数,并传参,获取返回值
参考上例
- 将需要传递的参数依次跟在函数名后面;
- 使用 QFuture<T> 的 result() 方法获取返回值;
(3)执行非const成员函数
QFuture<QString> f1 = QtConcurrent::run(this, &MainWindow::Hello, QString("Alice"));
QFuture<QString> f2 = QtConcurrent::run(&threadPool, this, &MainWindow::Hello, QString("Bob"));
- 线程池和传参以及返回值相同;
- 既然是成员,则需要指定实例,且是非const,则可能需要修改成员,在函数名前传入实例指针或者实例的应用;
(4)执行const成员
// call 'QList<QByteArray> QByteArray::split(char sep) const' in a separate thread
QByteArray bytearray = "hello world";
QFuture<QList<QByteArray> > future = QtConcurrent::run(bytearray, &QByteArray::split, ',');
...
QList<QByteArray> result = future.result();
const成员不会使用非const成员,所以,传入指针/引用或或者形参并没有区别,上例中,就是传入了形参
Qt线程池的更多相关文章
- QT 线程池 + TCP 小试(一)线程池的简单实现
*免分资源链接点击打开链接http://download.csdn.net/detail/goldenhawking/4492378 很久以前做过ACE + MFC/QT 的中轻量级线程池应用,大概就 ...
- QT 线程池 + TCP 小试(三)实现最终功能
*免分资源链接点击打开链接http://download.csdn.net/detail/goldenhawking/4492378 有了TCP.线程池,我们就可以把他们连接起来.使用最简单的 QMa ...
- C++11消息队列 + Qt线程池 + QRunnable执行任务简单模型
1.模板类queue,包含头文件<queue>中,是一个FIFO队列. queue.push():在队列尾巴增加数据 queue.pop():移除队列头部数据 queue.font():获 ...
- Qt 线程池QThreadPool类、QRunnable类
QThreadPool类 用来管理 QThreads.此类中的所有函数都是线程安全的. 主要属性: 1.activeThreadCount: 此属性表示线程池中的活动线程数,通过activeThrea ...
- Qt多线程-QThreadPool线程池与QRunnable
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt多线程-QThreadPool线程池与QRunnable 本文地址:https:/ ...
- Qt中的多线程与线程池浅析+实例
1. Qt中的多线程与线程池 今天学习了Qt中的多线程和线程池,特写这篇博客来记录一下 2. 多线程 2.1 线程类 QThread Qt 中提供了一个线程类,通过这个类就可以创建子线程了,Qt 中一 ...
- Qt 学习之路 :Qt 线程相关类
希望上一章有关事件循环的内容还没有把你绕晕.本章将重新回到有关线程的相关内容上面来.在前面的章节我们了解了有关QThread类的简单使用.不过,Qt 提供的有关线程的类可不那么简单,否则的话我们也没必 ...
- C#线程池用法
C#线程池用法 在C#编程语言中,使用线程池可以并行地处理工作,当强制线程和更新进度条时,会使用内建架构的ThreadPool类,为批处理使用多核结构,这里我们来看在C#编程语言中一些关于来自Syst ...
- Qt 线程基础
(转自:http://my.oschina.net/laopiao/blog/88158) 何谓线程? 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据 ...
随机推荐
- 背景知识+监督和无监督学习辨析+预备知识(1-1—1-4/用时4h)
1-1/1.2,基本上都是一些基础知识,机器学习的背景,发展,概念,用途 1-3,监督学习: 数据集类型已知,数据信息为已知正解--由已知正解推测趋势(拟合分布函数)-- 给出的模型例子--基本类似于 ...
- 【DataBase】更改root根用户密码 和 SQLyog安装
更改root根用户密码 和 SQLyog安装 无密码登录MySQL mysql -u root -p 修改密码与更新加密规则 ALTER USER 'root'@'localhost' IDENTIF ...
- sqli-labs通关教程----21~30关
第二十一关 第二十一关我们正常登陆后看到,uname后面变成了一堆字母 这是经过base64编码之后的样子,所以就照葫芦画瓢,将我payload的uname后面的部分转码成base64,这里可以用正常 ...
- 【LeetCode】 99. Recover Binary Search Tree [Hard] [Morris Traversal] [Tree]
Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...
- 关于vue切换用户,路由表不更新问题
简介 我想很多同学在项目中可能会遇到类似的问题,然后一顿操作,发现结果不尽人意.于是查阅各种资料,走进很多坑(可能你阅读的这篇随笔也是个坑).接下来我所描述的是关于我使用不同权限的用户切换登陆后,需要 ...
- python3_learn 实现文件夹内批量对图片重命名
初衷 练习Python,提高动手能力. 珍藏的壁纸文件夹名命有点乱. 可以学习下一些基础的库 开始(.jpg,无筛选) First 首先找到OS库,寻找可以遍历文件名的.找到了OS.walk() os ...
- Java中BigDecimal类
由于在运算的时候,float类型和double很容易丢失精度,演示案例,所以,为了能精确地表示.计算浮点数,Java提供了BIgDecimal BigDecimal类的概述 不可变的.任意精度的有符号 ...
- Python软件定时器APScheduler使用【软件定时器,非操作系统定时器,软件可控的定时器】【用途:定时同步数据库和缓存等】【刘新宇】
APScheduler使用 APScheduler (advanceded python scheduler)是一款Python开发的定时任务工具. 文档地址 https://apscheduler. ...
- thinkphp5--多文件入口设置
来源:http://www.cnblogs.com/walblog/p/8035426.html 今天在用tp5做项目的时候发现,前台是可以绑定默认到index模块的,但是后台不好弄,于是查了一下手册 ...
- Data Flow Diagram with Examples - Customer Service System
Data Flow Diagram with Examples - Customer Service System Data Flow Diagram (DFD) provides a visual ...