Qt多线程的实现方式有:
1. 继承QThread类,重写run()方法
2. 使用moveToThread将一个继承QObject的子类移至线程,内部槽函数均在线程中执行
3. 使用QThreadPool,搭配QRunnable(线程池)
4. 使用QtConcurrent(线程池)
为什么要用线程池?
创建和销毁线程需要和OS交互,少量线程影响不大,但是线程数量太大,势必会影响性能,使用线程池可以减少这种开销。
一、继承QThread类,重写run()方法
缺点:
1. 每次新建一个线程都需要继承QThread,实现一个新类,使用不太方便。
2. 要自己进行资源管理,线程释放和删除。并且频繁的创建和释放会带来比较大的内存开销。
适用场景:QThread适用于那些常驻内存的任务。
1 //mythread.h
2 #ifndef MYTHREAD_H
3 #define MYTHREAD_H
4
5 #include <QThread>
6
7 class MyThread : public QThread
8 {
9 public:
10 MyThread();
11 void stop();
12
13 protected:
14 void run();
15
16 private:
17 volatile bool stopped;
18 };
19
20 #endif // MYTHREAD_H
1 //mythread.cpp
2 #include "mythread.h"
3 #include <QDebug>
4 #include <QString>
5
6 MyThread::MyThread()
7 {
8 stopped = false;
9 }
10
11
12
13 void MyThread::stop()
14 {
15 stopped = true;
16 }
17
18
19
20 void MyThread::run()
21 {
22 qreal i = 0;
23
24 while( !stopped )
25 {
26 qDebug() << QString("in MyThread: %1").arg(i);
27 sleep(1);
28 i++;
29 }
30 stopped = false;
31 }
1 //widget.h
2 #ifndef WIDGET_H
3 #define WIDGET_H
4
5 #include <QWidget>
6 #include "mythread.h"
7
8
9 QT_BEGIN_NAMESPACE
10 namespace Ui { class Widget; }
11 QT_END_NAMESPACE
12
13 class Widget : public QWidget
14 {
15 Q_OBJECT
16
17 public:
18 Widget(QWidget *parent = nullptr);
19 ~Widget();
20
21 private slots:
22 void on_startBut_clicked();
23
24 void on_stopBut_clicked();
25
26 private:
27 Ui::Widget *ui;
28 MyThread thread;
29 };
30 #endif // WIDGET_H
1 //widget.cpp
2
3 #include "widget.h"
4 #include "ui_widget.h"
5
6 Widget::Widget(QWidget *parent)
7 : QWidget(parent)
8 , ui(new Ui::Widget)
9 {
10 ui->setupUi(this);
11 ui->startBut->setEnabled(true);
12 ui->stopBut->setEnabled(false);
13 }
14
15 Wid