性能特性测试系列4——QT线程与std::thread(下)之QThread
2017-01-15 00:23
465 查看
序
一QThread
二两种用法
二互斥量锁条件变量原子操作及其他
三一张图
其实用法早就总结了,但是因为自身事务原因,一直没有比较他们间的效率,甚至各种互斥量,条件变量之间的效率,更多是集中看了下他们各自的api和特点,所以估计以后还需要补充或者是另开一篇来讲= =。
测试环境:Qt5.7,vs2015。
看不清楚图可以直接在官网看:传送门
1、继承自QObject(截图没截上)
2、启动线程:start()函数,启动后调用run()函数,run()执行完之后退出线程。
3、wait:有点类似std::thread 的join,但是需要指定时间,并且不是线程run函数结束后自动返回,如果不指定,默认会一直等待。所以我一般在用的过程中,需要退出的时候(或者调用quit),再wait。
图里已经说得很清楚了,那我就不在多说:
头文件:
cpp
使用:
2、信号槽方式(推荐用法):
至于为啥推荐呢,直接给个传送门吧:传送门
至于代码,官网给了例子:传送门
我再写个简化版的:
简而言之,你需要做的是把QObject对象,movetothread去,否则你调用的信号槽仍然是在主线程。
1、互斥量与自解锁:
如下图所示:
qt的互斥量只有简单的QMutex,当然,某种程度上是std::thread里那几种结合体,自解锁也只有一种,如果不记得std::thread有哪些,请看我上一篇。用法比较简单,我就不贴代码了。
2、读写锁与其自解锁:
所谓读写锁,顾名思义,即读锁定状态与写锁定状态是不一样的。例如指定某段读取区域为lockForRead(),则表示这段代码仅仅是对资源进行读取,没有改变,所有线程可以共享该资源,无需阻塞;另一段改写某资源区域为LockForWrite(),则表示这段代码需要改写资源,其他线程需要阻塞,同时,lockForRead()锁定的读取资源代码也会被锁住,别的线程无论是读还是写会阻塞。
3、信号量:
图中其实把函数介绍的比较清楚了,即先指定一定数量的信号量,在实际用的过程中可用于一个类似生产者消费者模式,一个线程负责生产,如果信号量没有空位置了,rlease(加一个位置),另一个线程负责消费,如果有空位置,就消费一个(acquire)。
4、条件变量:
前面两个读写锁和信号量这些还和std::thread提供的机制有区别(因为没有,当然,想实现也可以用互斥量这些自己写一个)。条件变量几乎是没啥差异,用法也都差不多,函数已经在图中列出来了。
5、原子操作:
官网传送门:传送门
一共就如图所示只有三种,int,integer,pointer,用法也没太大的区别,不记得在上一篇有没有说过,原子对象本身也是带锁的,多线程访问的时候不用担心上锁问题,是为细粒度锁(mutex这些是粗粒度锁)。
6、future:
qfuture依赖于Qt Concurrent,下图接上图:
官网传送门:传送门
简单的说就是一个异步方法,类似std::async,只执行一次的异步方法,具体概念用法图中已经解释了。
下图解释下QFuture和QFutureWatcher关系(官网例子):
7、QThreadPool:
其实这个不算线程机制,不应该放上来,随便看看:
如下图所示
参考资料:传送门
本次其实还有许多的东西可以说,只是做了个简单的图表,慢慢来,现在没有时间补充,总结完这些,其实理解上的话也比较简单,暂时就先这样,当做挖个坑吧= =。
ps:基本上,线程的一些特性就先这样,以后有时间再说,下期是网络编程,Qt的tcp和udp,以及asio的tcp,udp,时间未知。
一QThread
二两种用法
二互斥量锁条件变量原子操作及其他
三一张图
其实用法早就总结了,但是因为自身事务原因,一直没有比较他们间的效率,甚至各种互斥量,条件变量之间的效率,更多是集中看了下他们各自的api和特点,所以估计以后还需要补充或者是另开一篇来讲= =。
序
QThread的线程用法上与std::thread相比有较大的区别,4.4版本之前是继承的方式来使用线程(个人猜测可能是因为那会儿c++11还没出来,std::function和std::bind没有,所以继承是实现消息回调比较方便的方式,当然仅仅是猜测,有兴趣可以查证),但4.4之后开始,官方建议不要再用继承的方式来使用线程,而是通过信号槽的方式来取代。测试环境:Qt5.7,vs2015。
一、QThread:
如下图所示:看不清楚图可以直接在官网看:传送门
1、继承自QObject(截图没截上)
2、启动线程:start()函数,启动后调用run()函数,run()执行完之后退出线程。
3、wait:有点类似std::thread 的join,但是需要指定时间,并且不是线程run函数结束后自动返回,如果不指定,默认会一直等待。所以我一般在用的过程中,需要退出的时候(或者调用quit),再wait。
二、两种用法:
既然QThread有两种用法,那么就简单介绍下吧:图里已经说得很清楚了,那我就不在多说:
头文件:
class QtThreadFuncByThread : public QThread { public: void SetLoop(int loop); int GetSum(); protected: virtual void run(); private: int _Loop = 0; int _Sum = 0; };
cpp
void QtThreadFuncByThread::SetLoop(int loop) { this->_Loop = loop; } int QtThreadFuncByThread::GetSum() { return this->_Sum; } void QtThreadFuncByThread::run() { for(int i = 0; i < this->_Loop; ++i) { this->_Sum++; } int id =(int)QThread::currentThreadId(); emit Log::GetInstance()->LogStr(QString("qt继承方式子线程id: %1;"). arg(id)); }
使用:
QtThreadFuncByThread thread; thread.SetLoop(loop); thread.start(); thread.wait(100);
2、信号槽方式(推荐用法):
至于为啥推荐呢,直接给个传送门吧:传送门
至于代码,官网给了例子:传送门
我再写个简化版的:
QThread * thread = new QThread; QtThreadFuncClass* funcclass = new QtThreadFuncClass; funcclass->SetLoop(loop); funcclass->moveToThread(thread); QObject::connect(thread, &QThread::started, funcclass, &QtThreadFuncClass::ThreadFunc, Qt::DirectConnection); thread->start(); thread->wait(100);
简而言之,你需要做的是把QObject对象,movetothread去,否则你调用的信号槽仍然是在主线程。
二、互斥量,锁,条件变量,原子操作及其他:
其实std::thread有的那些互斥量,自解锁,条件变量,future,原子操作等,Qt里面也能找到对应的类,只是用法,和一些细节性的功能不太一致,其他大致都是相似的,所以我就简要的整理和汇总下:1、互斥量与自解锁:
如下图所示:
qt的互斥量只有简单的QMutex,当然,某种程度上是std::thread里那几种结合体,自解锁也只有一种,如果不记得std::thread有哪些,请看我上一篇。用法比较简单,我就不贴代码了。
2、读写锁与其自解锁:
所谓读写锁,顾名思义,即读锁定状态与写锁定状态是不一样的。例如指定某段读取区域为lockForRead(),则表示这段代码仅仅是对资源进行读取,没有改变,所有线程可以共享该资源,无需阻塞;另一段改写某资源区域为LockForWrite(),则表示这段代码需要改写资源,其他线程需要阻塞,同时,lockForRead()锁定的读取资源代码也会被锁住,别的线程无论是读还是写会阻塞。
3、信号量:
图中其实把函数介绍的比较清楚了,即先指定一定数量的信号量,在实际用的过程中可用于一个类似生产者消费者模式,一个线程负责生产,如果信号量没有空位置了,rlease(加一个位置),另一个线程负责消费,如果有空位置,就消费一个(acquire)。
4、条件变量:
前面两个读写锁和信号量这些还和std::thread提供的机制有区别(因为没有,当然,想实现也可以用互斥量这些自己写一个)。条件变量几乎是没啥差异,用法也都差不多,函数已经在图中列出来了。
5、原子操作:
官网传送门:传送门
一共就如图所示只有三种,int,integer,pointer,用法也没太大的区别,不记得在上一篇有没有说过,原子对象本身也是带锁的,多线程访问的时候不用担心上锁问题,是为细粒度锁(mutex这些是粗粒度锁)。
6、future:
qfuture依赖于Qt Concurrent,下图接上图:
官网传送门:传送门
简单的说就是一个异步方法,类似std::async,只执行一次的异步方法,具体概念用法图中已经解释了。
下图解释下QFuture和QFutureWatcher关系(官网例子):
7、QThreadPool:
其实这个不算线程机制,不应该放上来,随便看看:
三、一张图:
该图能较好说明QThread的一些用法及生命周期。如下图所示
参考资料:传送门
本次其实还有许多的东西可以说,只是做了个简单的图表,慢慢来,现在没有时间补充,总结完这些,其实理解上的话也比较简单,暂时就先这样,当做挖个坑吧= =。
ps:基本上,线程的一些特性就先这样,以后有时间再说,下期是网络编程,Qt的tcp和udp,以及asio的tcp,udp,时间未知。
相关文章推荐
- 性能特性测试系列3——QT线程与std::thread(上)之std::thread
- 性能特性测试系列2——c++11 std::function和正常调用函数效率比较
- 性能特性测试系列1——STL容器,QT容器性能相关比较和总结
- 性能测试线程队列阻塞的现象之一
- Loadrunner性能测试工具系列视频教学!(学测试的朋友请进!
- Ajax性能测试工具-Firefox插件系列
- BizTalk开发系列(三十七) 性能监视器在BizTalk性能测试中的使用
- 51Testing作品系列:性能测试从零开始——LoadRunner入门
- 做一个开发人员认可的测试人员(系列6)-如何使得机器的性能相当
- 【原】qt4 子线程给主线程发消息,发数据,通信,qthread gui postevent emit
- Java 7新特性及简单性能对比测试
- (转)C#线程系列讲座(2):Thread类的应用
- MySQL5.1新特性翻译系列 - 通过分区(Partition)提升MySQL性能
- Java 7:最新特性、代码示例及性能测试
- Java 7:最新特性、代码示例及性能测试
- C#线程系列讲座(2):Thread类的应用
- mysql 优化系列(一) Mysql数据库引擎性能测试
- [转]MySQL5.1新特性翻译系列 - 通过分区(Partition)提升MySQL性能
- 网店版重生系列:因为webwork.configuration.xml.reload遭遇Web应用性能测试瓶颈
- ruby 线程的性能测试