Summary of four ways to use multithreading under Qt and code examples


foreword

In the previous Qt development work, it was found that the use of multi-threading is relatively common. Here, I will summarize my previous experience and experience obtained after referring to other blog posts, and summarize several ways to realize multi-threading under Qt, and combine the corresponding examples. Everyone learns, if there are mistakes, everyone is welcome to criticize and correct.

1. Inherit QThread, rewrite the run() function;
2. Inherit QObject, use the moveToThread() function;
3. Inherit QRunnable, rewrite the run() function, and use the QThreadPool thread pool;
4. Use the run() function of QtConcurrent;

Project effect
Click the Start button in the four groupBoxes on the interface in turn, and you can see the printout in the figure below. You can see that the program has successfully started four threads through the thread number. In addition, if you click again, the QRunnable and QtConcurrent methods can be opened again. For new threads, the number of threads that can be opened is related to the current thread pool settings.
Please add a picture description


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

1. Inherit QThread and rewrite the run() function

1.qthreadrun.h

#ifndef QTHREADRUN_H
#define QTHREADRUN_H

#include <QThread>
#include <QDebug>

class QThreadRun : public QThread
{
    
    
    Q_OBJECT

public:
    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子线程号:"<<QThread::currentThread();
        QThread::msleep(1000);   //延时1000ms
    }
}

2. Inherit QObject and use the moveToThread() function

1.qmovetothread.h

#ifndef QMOVETOTHREAD_H
#define QMOVETOTHREAD_H

#include <QObject>
#include <QThread>
#include <QDebug>

class QMoveToThread : public QObject
{
    
    
    Q_OBJECT

public:
    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子线程号:"<<QThread::currentThread();
        QThread::msleep(1000);
    }
}

3. Inherit QRunnable, rewrite the run() function, and use the QThreadPool thread pool

1.qrunnablerun.h

#ifndef QRUNNABLERUN_H
#define QRUNNABLERUN_H

#include <QRunnable>
#include <QThread>
#include <QDebug>

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子线程号:"<<QThread::currentThread();
        QThread::msleep(1000);
    }
}

Fourth, use the run() function of QtConcurrent

1. Add the following code in the project file.pro file

QT   += concurrent

2. Add the header file

#include <QtConcurrent>

3. How to use

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

5. Example code

1.QThreadTest.pro

QT   += core gui
QT   += concurrent

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
    main.cpp \
    qmovetothread.cpp \
    qrunnablerun.cpp \
    qthreadrun.cpp \
    widget.cpp

HEADERS += \
    qmovetothread.h \
    qrunnablerun.h \
    qthreadrun.h \
    widget.h

FORMS += \
    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 <QWidget>
#include <QThreadPool>
#include <QtConcurrent>
#include "qthreadrun.h"
#include "qmovetothread.h"
#include "qrunnablerun.h"

QT_BEGIN_NAMESPACE
namespace Ui {
    
     class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    
    
    Q_OBJECT

public:
    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;

    //QThreadRun
    QThreadRun *m_QThreadRun;

    //QMoveToThread
    QThread *m_QThread;
    QMoveToThread *m_QMoveToThread;

    //QRunnableRun
    QThreadPool *m_QThreadPool;
    QRunnableRun *m_QRunnableRun;

    //QtConcurrentRun
    bool 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()
{
    
    
    //main
    qDebug()<<"Widget主线程号:"<<QThread::currentThread();

    //QThreadRun
    m_QThreadRun = new QThreadRun();

    //QMoveToThread
    m_QThread = new QThread(this);
    m_QMoveToThread = new QMoveToThread();
    connect(this,SIGNAL(signal_moveToThread()),m_QMoveToThread,SLOT(slot_moveToThread()),Qt::UniqueConnection);
    m_QMoveToThread->moveToThread(m_QThread);
    m_QThread->start();

    //QRunnableRun
    m_QThreadPool = new QThreadPool();
    m_QThreadPool->setMaxThreadCount(3);   //设置非全局线程池可容纳线程个数为3个
    m_QRunnableRun = new QRunnableRun();

    //QtConcurrentRun
    startFlag = false;
    //qDebug()<<QThreadPool::globalInstance()->maxThreadCount();   //获取全局线程池最大线程个数
    //QThreadPool::globalInstance()->setMaxThreadCount(10);        //设置全局线程池可容纳线程个数

}

void Widget::setSwitch(bool flag)
{
    
    
    startFlag = flag;
}

void Widget::myQtConcurrentRun()
{
    
    
    while(startFlag)
    {
    
    
        qDebug()<<"QtConcurrent子线程号"<<QThread::currentThread();
        QThread::msleep(1000);
    }
}

void Widget::myMainRun()
{
    
    
    while(startFlag)
    {
    
    
        qDebug()<<"当前线程号"<<QThread::currentThread();
        QThread::msleep(1000);
    }
}

//QThreadRun
void Widget::on_pb_start_clicked()
{
    
    
    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()<<"全局线程池当前线程数:"<<QThreadPool::globalInstance()->activeThreadCount();   //当前活动的线程个数

    //非全局线程池方式
    m_QThreadPool->start(m_QRunnableRun);
    qDebug()<<"非全局线程池当前线程数:"<<m_QThreadPool->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当前线程数:"<<QThreadPool::globalInstance()->activeThreadCount();   //当前活动的线程个数
}

void Widget::on_pb_stop_4_clicked()
{
    
    
    setSwitch(false);
}

//不使用多线程的对比测试,界面卡死
void Widget::on_pb_test_clicked()
{
    
    
    setSwitch(true);
    myMainRun();
}

4.widget.ui
Please add a picture description

6. Download link

My example Baidu network disk link: https://pan.baidu.com/s/1hpcXFA2vahZ0WV3pRUfqXQ
Extraction code: xxcj


Summarize

In the above method of realizing multi-threading, you can see that using the run() function of QtConcurrent does not need to inherit the class, nor does it need to rewrite the function. It is more convenient to use. One thing to note is that the thread obtained by this method It comes from the QThreadPool pool. If there are no idle threads in the QThreadPool pool, the thread may not be executed directly. When using QRunnable's run(), you can see that there are global thread pool and non-global thread pool to start. The global thread pool is the same as the QThreadPool of the QtConcurrent method. Here are several function prints about the thread pool:
QThreadPool::globalInstance()->maxThreadCount(); //Get the maximum number of threads in the thread pool
QThreadPool::globalInstance()->setMaxThreadCount(10); //Set the number of threads that the thread pool can accommodate
QThreadPool::globalInstance() ->activeThreadCount(); //The number of active threads in the current thread pool
For details about the advantages and disadvantages of several methods of multi-threading under Qt, you can check the reference article.


hello:
Learn together and make progress together. If you still have related questions, you can leave a message in the comment area for discussion.

Reference blog:
4 multi-threaded implementations of Qt
Several multi-threaded implementations of Qt

Guess you like

Origin blog.csdn.net/XCJandLL/article/details/125572670