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) 何谓线程? 线程与并行处理任务息息相关,就像进程一样.那么,线程与进程有什么区别呢?当你在电子表格上进行数据 ...
随机推荐
- 泛型方法或泛型类中的方法是内部调用、PInvoke 或是在 COM 导入类中定义的。
泛型基类中引用Api函数定义时static extern,在子类中会提示: 未处理TypeLoadException 泛型方法或泛型类中的方法是内部调用.PInvoke 或是在 COM 导入类中定义的 ...
- Python的炫技操作:条件语句的七种写法
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: Python极客社区 PS:如有需要Python学习资料的小伙伴可以 ...
- 并查集判树 poj 1308
例题: poj 1308 题目大意比较简单,对任意两个点,有且仅有一条道路,也就是一棵树. 题解:一棵树中,肯定是不能有环的,而且只能由一个根节点.(没认真读题,只知道在那里判环....),所以这个题 ...
- Linux安装PHP的Redis扩展(已安装Redis)
1.下载需要的php操作redis的扩展包 下载地址 http://pecl.php.net/package/redis 下载对应php版本,我的php版本为7.3,下载的是最新的版本5.0.2 ...
- 最新VMware虚拟机安装Linux系统-CentOS(详细教程)
一.前言 最近有网友反应初学Linx不会安装,找了许多教程不是太全面,总会遇到一些要不是启动不了,要不是连不上网,各种问题,为了让大家能够顺利的安装,小乐写了一个非常详细的教程,让大家少入坑. 二.背 ...
- HBase可用性分析与高可用实践
HBase作为一个分布式存储的数据库,它是如何保证可用性的呢?对于分布式系统的CAP问题,它是如何权衡的呢? 最重要的是,我们在生产实践中,又应该如何保证HBase服务的高可用呢? 下面我们来仔细分析 ...
- <cstring>中常用的两个函数memset()和memcpy()
<cstring>是c++对c中的<string.h>进行了重写,这两个头文件中的函数用法是一样的,所以在用的时候包含哪个头文件都行.下面介绍一下 <cstring> ...
- ajaxReturn案例
请查看:http://www.cnblogs.com/bushe/p/4625097.html 不用自己写json格式啦,直接拿这个用就可以啦
- 存储-raid
- Openstack Swift 如何查找 slave node 挂载的 VD 的 IP
1. 在 /etc/swift/container-server.conf 或者 object-server.conf 中的 devices= 一行 可以找到 /srv/node. 在 /srv/no ...