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 是在主

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

目录
相关文章
|
4天前
|
存储 运维 监控
深度体验阿里云系统控制台:SysOM 让 Linux 服务器监控变得如此简单
作为一名经历过无数个凌晨三点被服务器报警电话惊醒的运维工程师,我对监控工具有着近乎苛刻的要求。记得去年那次大型活动,我们的主站流量暴增,服务器内存莫名其妙地飙升到90%以上,却找不到原因。如果当时有一款像阿里云 SysOM 这样直观的监控工具,也许我就不用熬通宵排查问题了。今天,我想分享一下我使用 SysOM 的亲身体验,特别是它那令人印象深刻的内存诊断功能。
|
4天前
|
存储 缓存 Linux
Linux系统中如何查看CPU信息
本文介绍了查看CPU核心信息的方法,包括使用`lscpu`命令和读取`/proc/cpuinfo`文件。`lscpu`能快速提供逻辑CPU数量、物理核心数、插槽数等基本信息;而`/proc/cpuinfo`则包含更详细的配置数据,如核心ID和处理器编号。此外,还介绍了如何通过`lscpu`和`dmidecode`命令获取CPU型号、制造商及序列号,并解释了CPU频率与缓存大小的相关信息。最后,详细解析了`lscpu`命令输出的各项参数含义,帮助用户更好地理解CPU的具体配置。
34 8
|
1月前
|
Linux
Linux系统之whereis命令的基本使用
Linux系统之whereis命令的基本使用
77 24
Linux系统之whereis命令的基本使用
|
2月前
|
缓存 安全 Linux
Linux系统查看操作系统版本信息、CPU信息、模块信息
在Linux系统中,常用命令可帮助用户查看操作系统版本、CPU信息和模块信息
167 23
|
3月前
|
安全 网络协议 Linux
telnet在windows和linux上的使用方法
Telnet是一个简单且强大的网络工具,广泛用于远程管理和网络诊断。尽管存在安全风险,但在受控环境中,Telnet仍然是一个非常有用的工具。通过本文的介绍,您应该能够在Windows和Linux系统上安装并使用Telnet进行各种网络操作。
270 18
|
3月前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
138 13
|
1月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
49 17
|
1月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
61 26
|
3月前
|
安全 Java API
【JavaEE】多线程编程引入——认识Thread类
Thread类,Thread中的run方法,在编程中怎么调度多线程
|
3月前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
288 2