Qt下多线程的四种使用方法总结及代码示例
创始人
2024-03-20 07:49:33
0

文章目录

  • 前言
  • 一、继承QThread,重写run()函数
  • 二、继承QObject,使用moveToThread()函数
  • 三、继承QRunnable,重写run()函数,使用QThreadPool线程池
  • 四、使用QtConcurrent的run()函数
  • 五、示例代码
  • 六、下载链接
  • 总结


前言

在之前的Qt开发工作中,发现多线程的使用比较常见,这里将自己之前经历以及参考其它博文后获取的经验,对Qt下实现多线程的几种方式进行总结,并结合相应的示例,以便大家学习,如有错误之处,欢迎大家批评指正。

1.继承QThread,重写run()函数;
2.继承QObject,使用moveToThread()函数;
3.继承QRunnable,重写run()函数,使用QThreadPool线程池;
4.使用QtConcurrent的run()函数;

项目效果
依次点击界面上的四个groupBox中的Start按钮,可以看到下图的打印输出,通过线程号可以看到程序成功启动了四条线程,另外再次点击的话,QRunnable及QtConcurrent的方式可以再开启新的线程,所能开启的线程数量以当前线程池的设置有关。
请添加图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

一、继承QThread,重写run()函数

1.qthreadrun.h

#ifndef QTHREADRUN_H
#define QTHREADRUN_H#include 
#include class QThreadRun : public QThread
{Q_OBJECTpublic:QThreadRun();~QThreadRun();void setSwitch(bool flag);void run();private:bool startFlag;
};
#endif // QTHREADRUN_H

2.qthreadrun.cpp

#include "qthreadrun.h"QThreadRun::QThreadRun()
{startFlag = false;
}QThreadRun::~QThreadRun()
{}void QThreadRun::setSwitch(bool flag)
{startFlag = flag;
}void QThreadRun::run()
{while(startFlag){qDebug()<<"QThreadRun子线程号:"<

二、继承QObject,使用moveToThread()函数

1.qmovetothread.h

#ifndef QMOVETOTHREAD_H
#define QMOVETOTHREAD_H#include 
#include 
#include class QMoveToThread : public QObject
{Q_OBJECTpublic:QMoveToThread();~QMoveToThread();void setSwitch(bool flag);public slots:void slot_moveToThread();private:bool startFlag;
};
#endif // QMOVETOTHREAD_H

2.qmovetothread.cpp

#include "qmovetothread.h"QMoveToThread::QMoveToThread()
{startFlag = false;
}QMoveToThread::~QMoveToThread()
{}void QMoveToThread::setSwitch(bool flag)
{startFlag = flag;
}void QMoveToThread::slot_moveToThread()
{while(startFlag){qDebug()<<"QMoveToThread子线程号:"<

三、继承QRunnable,重写run()函数,使用QThreadPool线程池

1.qrunnablerun.h

#ifndef QRUNNABLERUN_H
#define QRUNNABLERUN_H#include 
#include 
#include class QRunnableRun : public QRunnable
{
public:QRunnableRun();~QRunnableRun();void setSwitch(bool flag);void run();private:bool startFlag;
};
#endif // QRUNNABLERUN_H

2.qrunnablerun.cpp

#include "qrunnablerun.h"QRunnableRun::QRunnableRun()
{startFlag = false;
}QRunnableRun::~QRunnableRun()
{}void QRunnableRun::setSwitch(bool flag)
{startFlag = flag;
}void QRunnableRun::run()
{while(startFlag){qDebug()<<"QRunnableRun子线程号:"<

四、使用QtConcurrent的run()函数

1.在工程文件.pro文件中添加下面这句代码

QT   += concurrent

2.添加头文件

#include 

3.使用方式

...
//详细代码见下文
QtConcurrent::run(this,&Widget::myQtConcurrentRun);
...

五、示例代码

1.QThreadTest.pro

QT   += core gui
QT   += concurrentgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11DEFINES += QT_DEPRECATED_WARNINGSSOURCES += \main.cpp \qmovetothread.cpp \qrunnablerun.cpp \qthreadrun.cpp \widget.cppHEADERS += \qmovetothread.h \qrunnablerun.h \qthreadrun.h \widget.hFORMS += \widget.ui# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

2.widget.h

#ifndef WIDGET_H
#define WIDGET_H#include 
#include 
#include 
#include "qthreadrun.h"
#include "qmovetothread.h"
#include "qrunnablerun.h"QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void initThread();void setSwitch(bool flag);void myQtConcurrentRun();void myMainRun();signals:void signal_moveToThread();private slots:void on_pb_start_clicked();void on_pb_stop_clicked();void on_pb_start_2_clicked();void on_pb_stop_2_clicked();void on_pb_start_3_clicked();void on_pb_stop_3_clicked();void on_pb_start_4_clicked();void on_pb_stop_4_clicked();void on_pb_test_clicked();private:Ui::Widget *ui;//QThreadRunQThreadRun *m_QThreadRun;//QMoveToThreadQThread *m_QThread;QMoveToThread *m_QMoveToThread;//QRunnableRunQThreadPool *m_QThreadPool;QRunnableRun *m_QRunnableRun;//QtConcurrentRunbool startFlag;
};
#endif // WIDGET_H

3.widget.cpp

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->initThread();
}Widget::~Widget()
{delete ui;
}void Widget::initThread()
{//mainqDebug()<<"Widget主线程号:"<moveToThread(m_QThread);m_QThread->start();//QRunnableRunm_QThreadPool = new QThreadPool();m_QThreadPool->setMaxThreadCount(3);   //设置非全局线程池可容纳线程个数为3个m_QRunnableRun = new QRunnableRun();//QtConcurrentRunstartFlag = false;//qDebug()<maxThreadCount();   //获取全局线程池最大线程个数//QThreadPool::globalInstance()->setMaxThreadCount(10);        //设置全局线程池可容纳线程个数}void Widget::setSwitch(bool flag)
{startFlag = flag;
}void Widget::myQtConcurrentRun()
{while(startFlag){qDebug()<<"QtConcurrent子线程号"<while(startFlag){qDebug()<<"当前线程号"<m_QThreadRun->setSwitch(true);m_QThreadRun->start();
}void Widget::on_pb_stop_clicked()
{m_QThreadRun->setSwitch(false);
}//QMoveToThread
void Widget::on_pb_start_2_clicked()
{m_QMoveToThread->setSwitch(true);//m_QMoveToThread->slot_moveToThread();   不能直接调用处理函数,函数还是在主线程中运行emit signal_moveToThread();   //发送信号启动子线程处理函数
}void Widget::on_pb_stop_2_clicked()
{m_QMoveToThread->setSwitch(false);
}//QRunnableRun
void Widget::on_pb_start_3_clicked()
{m_QRunnableRun->setSwitch(true);//全局线程池方式//QThreadPool::globalInstance()->start(m_QRunnableRun);//qDebug()<<"全局线程池当前线程数:"<activeThreadCount();   //当前活动的线程个数//非全局线程池方式m_QThreadPool->start(m_QRunnableRun);qDebug()<<"非全局线程池当前线程数:"<activeThreadCount();   //当前活动的线程个数}void Widget::on_pb_stop_3_clicked()
{m_QRunnableRun->setSwitch(false);
}//QtConcurrentRun
void Widget::on_pb_start_4_clicked()
{setSwitch(true);QtConcurrent::run(this,&Widget::myQtConcurrentRun);qDebug()<<"QtConcurrentRun当前线程数:"<activeThreadCount();   //当前活动的线程个数
}void Widget::on_pb_stop_4_clicked()
{setSwitch(false);
}//不使用多线程的对比测试,界面卡死
void Widget::on_pb_test_clicked()
{setSwitch(true);myMainRun();
}

4.widget.ui
请添加图片描述

六、下载链接

我的示例百度网盘链接:https://pan.baidu.com/s/1hpcXFA2vahZ0WV3pRUfqXQ
提取码:xxcj


总结

在上述实现多线程的方法中,可以看到使用QtConcurrent的run()函数是不需要继承类,也不需要重写函数的,使用起来比较方便,需要注意的一点是,通过该方式获取的线程是来自QThreadPool池,如果QThreadPool池中没有空闲的线程,该线程可能不会直接执行。使用QRunnable的run()的时候可以看到有全局线程池和非全局线程池方式来进行start,其中的全局线程池跟QtConcurrent方法的QThreadPool是同一个,这里有几个关于线程池的函数打印:
QThreadPool::globalInstance()->maxThreadCount(); //获取线程池最大线程个数
QThreadPool::globalInstance()->setMaxThreadCount(10); //设置线程池可容纳线程个数
QThreadPool::globalInstance()->activeThreadCount(); //当前线程池活动的线程个数
有关于Qt下多线程几种方式的优缺点等详细内容,可以查看参考文章。


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。

参考博客:
Qt的4种多线程实现方式
Qt几种多线程的实现

相关内容

热门资讯

汽车油箱结构是什么(汽车油箱结... 本篇文章极速百科给大家谈谈汽车油箱结构是什么,以及汽车油箱结构原理图解对应的知识点,希望对各位有所帮...
重大消息战皇大厅开挂是真的吗... 您好:战皇大厅这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
嵌入式 ADC使用手册完整版 ... 嵌入式 ADC使用手册完整版 (188977万字)💜&#...
盘点十款牵手跑胡子为什么一直... 您好:牵手跑胡子这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游...
senator香烟多少一盒(s... 今天给各位分享senator香烟多少一盒的知识,其中也会对sevebstars香烟进行解释,如果能碰...
终于懂了新荣耀斗牛真的有挂吗... 您好:新荣耀斗牛这款游戏可以开挂,确实是有挂的,需要了解加客服微信8435338】很多玩家在这款游戏...
盘点十款明星麻将到底有没有挂... 您好:明星麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【5848499】很多玩家在这款游戏...
总结文章“新道游棋牌有透视挂吗... 您好:新道游棋牌这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7682267】很多玩家在这款游...
终于懂了手机麻将到底有没有挂... 您好:手机麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
领奥平衡车质量怎么样(左拉和领... 本篇文章极速百科给大家谈谈领奥平衡车质量怎么样,以及左拉和领奥平衡车哪个好对应的知识点,希望对各位有...