linux系统中QT里面多线程的使用方法

简介: linux系统中QT里面多线程的使用方法

     大家好,今天主要和大脚聊一聊,如何使用QT中的多线程的方法。

 

第一:多线程基本简介

      QThread 线程类是实现多线程的核心类。Qt 有两种多线程的方法,其中一种是继承 QThread 的 run()函数,另外一种是把一个继承于 QObject 的类转移到一个 Thread 里。Qt4.8 之前都是使用继承 QThread run()这种方法,但是 Qt4.8 之后,Qt 官方建议使用第二种方法。两种方法区 别不大,用起来都比较方便,但继承 QObject 的方法更加灵活。所以 Qt 的帮助文档里给的参考是先给继承 QObject 的类,然后再给继承 QThread 的类。另外 Qt 提供了 QMutexQMutexLockerQReadLocker QWriteLocker 等类用于线程之间的同步,详细可以看 Qt 的帮助文档。

       

       通过上面的图我们可以看到,主线程内有很多方法在主线程内,但是子线程,只有 run() 方法是在子线程里的。run()方法是继承于 QThread 类的方法,用户需要重写这个方法,一般是把耗时的操作写在这个 run()方法里面。

第二:应用实例实现

        通过 QThread 类继承线程,然后在 MainWindow 类里使用。通过点击一个按钮开启线程。当线程执行完成时,会发送 resultReady(const QString &s)信号给主线程。

1 #ifndef MAINWINDOW_H
2 #define MAINWINDOW_H
3
4 #include <QMainWindow>
5 #include <QThread>
6 #include <QDebug>
7 #include <QPushButton>
8
9 /* 使用下面声明的 WorkerThread 线程类 */
10 class WorkerThread;
11
12 class MainWindow : public QMainWindow
13 {
14 Q_OBJECT
15
16 public:
17 MainWindow(QWidget *parent = nullptr);
18 ~MainWindow();
19
20 private:
21 /* 在 MainWindow 类里声明对象 */
22 WorkerThread *workerThread;
23
24 /* 声明一个按钮,使用此按钮点击后开启线程 */
25 QPushButton *pushButton;
26
27 private slots:
28 /* 槽函数,用于接收线程发送的信号 */
29 void handleResults(const QString &result);
30
31 /* 点击按钮开启线程 */
32 void pushButtonClicked();
33 };
34
35 /* 新建一个 WorkerThread 类继承于 QThread */
36 class WorkerThread : public QThread
37 {
38 /* 用到信号槽即需要此宏定义 */
39 Q_OBJECT
40
41 public:
42 WorkerThread(QWidget *parent = nullptr) {
43 Q_UNUSED(parent);
44 }
45
46 /* 重写 run 方法,继承 QThread 的类,只有 run 方法是在新的线程里 */
47 void run() override {
48 QString result = "线程开启成功";
49
50 /* 这里写上比较耗时的操作 */
51 // ...
52 // 延时 2s,把延时 2s 当作耗时操作
53 sleep(2);
54
55 /* 发送结果准备好的信号 */
56 emit resultReady(result);
57 }
58
59 signals:
60 /* 声明一个信号,译结果准确好的信号 */
61 void resultReady(const QString &s);
62 };
63
64 #endif // MAINWINDOW_H
65

36 行,声明一个 WorkerThread 的类继承 QThread 类,这里是参考 Qt QThread 类的帮

助文档的写法。

47 行,重写 run()方法,这里很重要。把耗时操作写于此,本例相当于一个继承 QThread

类线程模板了。

第三:源文件的代码具体实现

1 #include "mainwindow.h"
2
3 MainWindow::MainWindow(QWidget *parent)
4 : QMainWindow(parent)
5 {
6 /* 设置位置与大小 */
7 this->setGeometry(0, 0, 800, 480);
8
9 /* 对象实例化 */
10 pushButton = new QPushButton(this);
11 workerThread = new WorkerThread(this);
12
13 /* 按钮设置大小与文本 */
14 pushButton->resize(100, 40);
15 pushButton->setText("开启线程");
16
17 /* 信号槽连接 */
18 connect(workerThread, SIGNAL(resultReady(QString)),
19 this, SLOT(handleResults(QString)));
20 connect(pushButton, SIGNAL(clicked()),
21 this, SLOT(pushButtonClicked()));
22 }
23
24 MainWindow::~MainWindow()
25 {
26 /* 进程退出,注意本例 run()方法没写循环,此方法需要有循环才生效 */
27 workerThread->quit();
28
29 /* 阻塞等待 2000ms 检查一次进程是否已经退出 */
30 if (workerThread->wait(2000)) {
31 qDebug()<<"线程已经结束!"<<endl;
32 }
33 }
34
35 void MainWindow::handleResults(const QString &result)
36 {
37 /* 打印出线程发送过来的结果 */
38 qDebug()<<result<<endl;
39 }
40
41 void MainWindow::pushButtonClicked()
42 {
43 /* 检查线程是否在运行,如果没有则开始运行 */
44 if (!workerThread->isRunning())
45 workerThread->start();
46 }

11 行,线程对象实例化,Qt 使用 C++基本都是对象编程,Qt 线程也不例外。所以我们

也是用对象来管理线程的。

24~33 行,在 MainWindow 的析构函数里退出线程,然后判断线程是否退出成功。因为

我们这个线程是没有循环操作的,直接点击按钮开启线程后,做了 2s 延时操作后就完成了。所

以我们在析构函数里直接退出没有关系。

41~46 行,按钮点击后开启线程,首先我们得判断这个线程是否在运行,如果不在运行

我们则开始线程,开始线程用 start()方法,它会调用重写的 run()函数的。

第四:程序运行效果

       点击开启线程按钮后,延时 2s 后,Qt Creator 的应用程序输出窗口打印出“线程开启成功”。

2s 内多次点击按钮则不会重复开启线程,因为线程在这 2s 内还在运行。同时我们可以看到

点击按钮没卡顿现象。因为这个延时操作是在我们创建的线程里运行的,而 pushButton 是在主

线程里的,通过点击按钮控制子线程的运行。

目录
相关文章
|
2月前
|
缓存 监控 Linux
Linux系统清理缓存(buff/cache)的有效方法。
总结而言,在大多数情形下你不必担心Linux中buffer与cache占用过多内存在影响到其他程序运行;因为当程序请求更多内存在没有足够可用资源时,Linux会自行调整其占有量。只有当你明确知道当前环境与需求并希望立即回收这部分资源给即将运行重负载任务之前才考虑上述方法去主动干预。
774 10
|
2月前
|
安全 Linux 数据安全/隐私保护
为Linux系统的普通账户授予sudo访问权限的过程
完成上述步骤后,你提升的用户就能够使用 `sudo`命令来执行管理员级别的操作,而无需切换到root用户。这是一种更加安全和便捷的权限管理方式,因为它能够留下完整的权限使用记录,并以最小权限的方式工作。需要注意的是,随意授予sudo权限可能会使系统暴露在风险之中,尤其是在用户不了解其所执行命令可能带来的后果的情况下。所以在配置sudo权限时,必须谨慎行事。
324 0
|
2月前
|
Ubuntu Linux 开发者
国产 Linux 发行版再添新成员,CutefishOS 系统简单体验
当然,系统生态构建过程并不简单,不过为了帮助国产操作系统优化生态圈,部分企业也开始用国产操作系统替代 Windows,我们相信肯定会有越来越多的精品软件登录 Linux 平台。
120 0
|
2月前
|
Ubuntu 安全 Linux
Linux系统入门指南:从零开始学习Linux
Shell脚本是一种强大的自动化工具,可以帮助您简化重复的任务或创建复杂的脚本程序。了解Shell脚本的基本语法和常用命令,以及编写和运行Shell脚本的步骤,将使您更高效地处理日常任务。
210 0
|
2月前
|
Ubuntu Linux 图形学
Linux学习之Linux桌面系统有哪些?
Cinnamon:与MATE类似,Cinnamon 拥有 GNOME 和 Unity 等其它桌面环境所没有的种种功能,是高度可定制的桌面环境,不需要任何外部插件、窗口组件和调整工具来定制桌面。
126 0
|
12月前
|
安全 Linux
Linux线程(十一)线程互斥锁-条件变量详解
Linux线程(十一)线程互斥锁-条件变量详解
|
安全 算法 Linux
【Linux】线程安全——补充|互斥、锁|同步、条件变量(下)
【Linux】线程安全——补充|互斥、锁|同步、条件变量(下)
118 0
|
存储 安全 Linux
【Linux】线程安全——补充|互斥、锁|同步、条件变量(上)
【Linux】线程安全——补充|互斥、锁|同步、条件变量(上)
122 0
|
安全 Linux 调度
【linux线程(二)】线程互斥与线程同步
【linux线程(二)】线程互斥与线程同步