免费做网站建设一键优化是什么意思
1. Qt 创建线程的三种方法
1.1 方式一:派生于 QThread
-
派生于 QThread,这是 Qt 创建线程最常用的方法,重写虚函数 void QThread::run(),在 run() 写具体的内容,外部通过 start 调用,即可执行线程体 run()
- 派生于 QThread 的类,构造函数属于主线程,run() 函数属于子线程,可以通过打印线程 id 判断
-
main.cpp
#include <QCoreApplication>
#include <iostream>
#include "thread01.h"int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);std::cout << "main thread " << QThread::currentThreadId() << std::endl;Thread01 *th = new Thread01();th->start();std::cout << "main thread end" << std::endl;return a.exec();
}
- thread01.h
#pragma once
#include <QThread>class Thread01 : public QThread {Q_OBJECTpublic:Thread01();void run() override;
};
- thread01.cpp
#include "thread01.h"
#include <QDebug>Thread01::Thread01() {qDebug() << "Thread01 construct " << QThread::currentThreadId();
}void Thread01::run() {qDebug() << "Thread01 run " << QThread::currentThreadId();int index = 0;while (1) {qDebug() << index++;QThread::msleep(500);}
}
- 控制台输出
main thread 00004A20
Thread01 construct 0x4a20 // 构造函数属于主线程
Thread01 run 0x4f18 // run() 函数属于子线程
0
main thread end
1
2
3
...
1.2 方式二:派生于 QRunnable
-
派生于 QRunnable,重写 run() 方法,在 run() 方法里处理其它任务,调用时需要借助 Qt 线程池
- 这种新建线程的方法的缺点是:不能使用 Qt 的信号与槽机制,因为 QRunnable 不是继承自 QObject
- 但这种方法的好处是:可以让 QThreadPool 来管理线程,QThreadPool 会自动清理新建的 QRunnable 对象
-
main.cpp
#include <QCoreApplication>
#include <iostream>
#include "thread02.h"
#include <QThreadPool>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);std::cout << "main thread" << QThread::currentThreadId() << std::endl;Thread02 *th = new Thread02();QThreadPool::globalInstance()->start(th);std::cout << "main thread end" << std::endl;return a.exec();
}
- thread02.h
#pragma once
#include <QRunnable>class Thread02 : public QRunnable {
public:Thread02();~Thread02();void run() override;
};
- thread02.cpp
#include "thread02.h"
#include <QThread>
#include <QDebug>Thread02::Thread02() {qDebug() << "Thread02 construct " << QThread::currentThreadId();
}Thread02::~Thread02() {qDebug() << "Thread02 xigou func";
}void Thread02::run() {qDebug() << "Thread02 run " << QThread::currentThreadId();
}
1.3 moveToThread
-
派生于 QObject,使用 moveToThread 方法
- 将 QThread 对象作为私有成员,在构造函数里 moveToThread,然后启动线程
-
ch71_moveToThread.h
#pragma once#include <QtWidgets/QWidget>
#include "ui_ch71_moveToThread.h"
#include "Thread03.h"class ch71_moveToThread : public QWidget {Q_OBJECTpublic:ch71_moveToThread(QWidget *parent = nullptr);~ch71_moveToThread();private slots:void on_pushButton_clicked();signals:void sig_fun();private:Ui::ch71_moveToThreadClass ui;Thread03* m_pTh03 = nullptr;
};
- ch71_moveToThread.cpp
#include "ch71_moveToThread.h"
#include <QDebug>ch71_moveToThread::ch71_moveToThread(QWidget *parent) : QWidget(parent) {ui.setupUi(this);qDebug() << "main construct " << QThread::currentThreadId();m_pTh03 = new Thread03();connect(this, &ch71_moveToThread::sig_fun, m_pTh03, &Thread03::fun);
}ch71_moveToThread::~ch71_moveToThread() {}void ch71_moveToThread::on_pushButton_clicked() {emit sig_fun();
}
- Thread03.h
#pragma once
#include <QObject>
#include <QThread>class Thread03 : public QObject {
public:Thread03();public slots:void fun();private:QThread m_th;
};
- Thread03.cpp
#include "Thread03.h"
#include <QDebug>Thread03::Thread03() {this->moveToThread(&m_th);m_th.start();qDebug() << "Thread03 construct " << QThread::currentThreadId();
}void Thread03::fun() {qDebug() << "Thread03 fun " << QThread::currentThreadId();int index = 0;while (1) {qDebug() << index++;QThread::msleep(300);}
}
- 控制台输出
main construct 0x11f0
Thread03 construct 0x11f0
// 点击按钮后
Thread03 fun 0x2b74
0
1
2
3
...
2. Qt 并发
2.1 QtConcurrent 基本用法
- ch72_concurrent.h
#pragma once#include <QtWidgets/QWidget>
#include "ui_ch72_concurrent.h"class ch72_concurrent : public QWidget {Q_OBJECTpublic:ch72_concurrent(QWidget *parent = nullptr);~ch72_concurrent();int timeTask();private slots:void on_pushButton_clicked();private:Ui::ch72_concurrentClass ui;
};
- ch72_concurrent.cpp
#include "ch72_concurrent.h"
#include <QThread>
#include <QDebug>
#include <QtConcurrent>
#include <QFuture>ch72_concurrent::ch72_concurrent(QWidget *parent) : QWidget(parent) {ui.setupUi(this);
}ch72_concurrent::~ch72_concurrent() {}int ch72_concurrent::timeTask() {int num = 0;for (int i = 0; i < 1000000; i++) {num++;qDebug() << num;}return num;
}void ch72_concurrent::on_pushButton_clicked() {//timeTask();QFuture<int> ft = QtConcurrent::run(this, &ch72_concurrent::timeTask);while (!ft.isFinished()) {// 当 future 未完成时,让 cpu 去做别的事情QApplication::processEvents(QEventLoop::AllEvents, 30);}
}
2.2 QtConcurrent run() 参数说明
- QtConcurrent::run 函数参数,可以是全局函数,也可以是类成员函数
- ch73_concurrent.cpp
#include "ch73_concurrent.h"
#include <QDebug>
#include <QtConcurrent>
#include <QFuture>ch73_concurrent::ch73_concurrent(QWidget *parent) : QWidget(parent) {ui.setupUi(this);
}ch73_concurrent::~ch73_concurrent() {}int ch73_concurrent::timeTask(int num1, int num2) {//int num = 0;for (int i = 0; i < 1000000; i++) {num1++;num2++;qDebug() << num1;qDebug() << num2;}return num1 + num2;
}int gTimeTask(int num1, int num2) {//int num = 0;for (int i = 0; i < 1000000; i++) {num1++;num2++;qDebug() << num1;qDebug() << num2;}return num1 + num2;
}void ch73_concurrent::on_pushButton_clicked() {//timeTask();int num1 = 0;int num2 = 0;//QFuture<int> ft = QtConcurrent::run(this, &ch73_concurrent::timeTask, num1, num2);QFuture<int> ft = QtConcurrent::run(gTimeTask, num1, num2);while (!ft.isFinished()) {QApplication::processEvents(QEventLoop::AllEvents, 30);}
}
2.3 获取 QtConcurrent 的返回值
- 获取 QtConcurrent 的结果,需要使用 QFutureWatcher 类,链接它的信号 finished,然后给 watcher 设置 future,当监控到 future 执行结束后,可以获取它的执行结果,调用的是 result() 函数
- ch74.cpp
#include "ch74.h"
#include <QDebug>
#include <QtConcurrent>
#include <QFuture>
#include <QFutureWatcher>ch74::ch74(QWidget *parent) : QWidget(parent) {ui.setupUi(this);
}ch74::~ch74() {}int ch74::timeTask(int& num1, int& num2) {for (int i = 0; i < 1000; i++) {num1++;num2++;qDebug() << num1;qDebug() << num2;}return num1 + num2;
}void ch74::on_pushButton_clicked() {int num1 = 0;int num2 = 0;QFutureWatcher<int>* fw = new QFutureWatcher<int>;connect(fw, &QFutureWatcher<int>::finished, [&]{qDebug() << "QFutureWatcher finished";qDebug() << "result = " << fw->result();});QFuture<int> ft = QtConcurrent::run(this, &ch74::timeTask, num1, num2);fw->setFuture(ft);while (!ft.isFinished()) {QApplication::processEvents(QEventLoop::AllEvents, 30);}
}
3. C++ 其他线程技术
- pthread:linux 线程
- win32-pthread, obs 的线程全部使用了 win32-pthread
- windows thread 类
- MFC thread类
- boost
- std::thread(推荐用这个,基于语言级别的跨平台 C++ 线程)