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

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

目录
相关文章
|
5月前
|
监控 Java 测试技术
Java并发编程最佳实践:设计高性能的多线程系统
Java并发编程最佳实践:设计高性能的多线程系统
75 1
|
3月前
|
存储 Windows
(13) Qt事件系统(two)
文章详细介绍了Qt事件系统,包括事件分发、自定义事件、事件传播机制、事件过滤以及事件与信号的区别。
124 3
(13) Qt事件系统(two)
|
3月前
|
监控 安全 算法
线程死循环确实是多线程编程中的一个常见问题,它可能导致应用程序性能下降,甚至使整个系统变得不稳定。
线程死循环是多线程编程中常见的问题,可能导致性能下降或系统不稳定。通过代码审查、静态分析、日志监控、设置超时、使用锁机制、测试、选择线程安全的数据结构、限制线程数、使用现代并发库及培训,可有效预防和解决死循环问题。
87 1
|
3月前
|
监控 安全 算法
线程死循环是多线程编程中的常见问题,可能导致应用性能下降甚至系统不稳定。
【10月更文挑战第6天】线程死循环是多线程编程中的常见问题,可能导致应用性能下降甚至系统不稳定。为了解决这一问题,可以通过代码审查、静态分析、添加日志监控、设置超时机制、使用锁和同步机制、进行全面测试、选用线程安全的数据结构、限制线程数量、利用现代并发库,并对团队进行培训等方法来预防和减少死循环的发生。尽管如此,多线程编程的复杂性仍需要持续监控和维护以确保系统稳定。
71 3
|
3月前
|
编解码 程序员
(12)Qt事件系统(one)
本文详细介绍了Qt事件系统,包括各种系统事件、鼠标事件、键盘事件、定时器等的处理方法和示例代码。
107 0
|
3月前
|
资源调度 Linux 调度
Linux C/C++之线程基础
这篇文章详细介绍了Linux下C/C++线程的基本概念、创建和管理线程的方法,以及线程同步的各种机制,并通过实例代码展示了线程同步技术的应用。
40 0
Linux C/C++之线程基础
|
4月前
|
网络协议 安全
QT多线程
本文详细介绍了在Qt中如何正确使用QThread以及信号槽跨线程的使用方式,包括线程的正确退出方法和QObject在不同线程中创建子对象时可能遇到的问题。同时,文章还提供了相关博客和资料的链接,用于进一步学习和参考。
|
4月前
|
数据库 数据库管理
qt对sqlite数据库多线程的操作
本文总结了在Qt中进行SQLite数据库多线程操作时应注意的四个关键问题,包括数据库驱动加载、加锁、数据库的打开与关闭,以及QsqlQuery变量的使用。
241 1
|
3月前
|
安全 Linux
Linux线程(十一)线程互斥锁-条件变量详解
Linux线程(十一)线程互斥锁-条件变量详解
|
4月前
自己动手写QT多线程demo
本文是作者关于如何编写Qt多线程demo的教程,介绍了如何实现多线程功能,包括可暂停和继续的功能。文章提供了部分示例代码,展示了如何创建线程类、启动和管理线程,以及线程间的通信。同时,还提供了相关参考资料和免费下载链接。