说明

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

  1. 继承 QThread,重写 run() 接口;
  2. 使用 moveToThread() 方法将 QObject 子类移至线程中,内部的所有使用信号槽的槽函数均在线程中执行;
  3. 使用 QThreadPool 线程池,搭配 QRunnable
  4. 使用 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();
  1. 如果,指定的QRunnable还没有执行,则从队列中移除
  2. 清空队列中还没有执行的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线程池的更多相关文章

  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. D - Yet Another Monster Killing Problem

    题目连接: https://codeforces.com/contest/1257/problem/D 题目大意: n个怪兽,m个英雄,每个怪兽有一定的能力值,每个英雄有一定的能力值和一定的耐力值.耐 ...

  2. [Yii2] 快速套模板,加载JS,CSS(HTML标签<base>)

    刚开始学,弄了好久,不知道怎么加载JS.CSS,以及怎么不加载YII2自带的模板!其实真的好简单! 补: 其实是我垃圾,YII2默认访问路径是WEB,所以把style文件放到web下就能加载! 首先把 ...

  3. HTML+CSS教程(一)简介及其基本标签的使用方法

    一.前端 HTML(结构):HyPer TEXT Markup LanguageCSS(样式): 样式就是对于结构的一种美化JavaScript(js: 行为/ 提供了用户和界面的交互方式)jQuer ...

  4. 模糊字符串匹配:FuzzyWuzzy

    FuzzyWuzzy 模糊字符串匹配,它使用Levenshtein Distance来计算简单易用的包中序列之间的差异. 前置条件 Python 2.7 or higher difflib pytho ...

  5. openssl查看证书细节 [转载]

    openssl x509部分命令 打印出证书的内容: openssl x509 -in cert.pem -noout -text 打印出证书的系列号 openssl x509 -in cert.pe ...

  6. JAVA企业级应用TOMCAT实战(二)

    使用普通用户运行 使用普通用户来部署服务是比较安全的做法 [root@tomcat application]# useradd -u tomcat [root@tomcat application]# ...

  7. 在Spring Boot中配置web app

    文章目录 添加依赖 配置端口 配置Context Path 配置错误页面 在程序中停止Spring Boot 配置日志级别 注册Servlet 切换嵌套服务器 在Spring Boot中配置web a ...

  8. RxJava--Buffer,GroupBy 对比

    Buffer 设定收集n个元素为一组,以下方代码为例,三个为一组,则当组满三个元素时,返回一次List数据 没组满三个元素时,如果调用onComplete,直接发送剩余元素,没调用onComplete ...

  9. 3DMAX导出到Unity坐标轴转换问题

      这是我在3dmax中创建的1cm*1cm*1cm的立方体,右图为3dmax中的坐标系 当我们把这个立方体导入到unity中发现x轴意外的扭转了90度 为了解决这个问题,你需要对模型做出修正 1.选 ...

  10. vue 跳转并传参,实现数据实时更新

    原文链接:点我 比如我现在在页面A跳转到页面B,A中的router-link :to={path:’B’,params:{id:’5’}} 求助:在页面B中的mounted生命周期函数中使用this. ...