当前位置: 首页 > news >正文

【QT学习十一】QThread

一、引言

        在现代软件开发中,多线程编程变得越来越重要,尤其是对于需要处理并发任务的应用程序。Qt C++ 框架提供了强大的多线程支持,使得开发者能够轻松地创建和管理多线程应用。

        在 Qt 中,多线程的实现主要基于 QThread 类。QThread 提供了一个线程对象,允许开发者通过继承 QThread 类并实现 run() 函数来定义线程的执行体

二、一个QThread实例

#include <QCoreApplication>
#include <QThread>
#include <QDebug>class MyThread : public QThread {
public:void run() override {for (int i = 0; i < 5; ++i) {qDebug() << "Thread is running" << i;sleep(1);}}
};int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);// 创建线程对象MyThread thread;// 启动线程thread.start();// 主线程继续执行其他任务for (int i = 0; i < 3; ++i) {qDebug() << "Main thread is running" << i;QThread::sleep(1);}// 等待线程结束thread.wait();return a.exec();
}

        在这个示例中,MyThread 类继承自 QThread,并重写了 run() 函数。在 main() 函数中,我们创建了 MyThread 的实例 thread,并通过 start() 启动了一个新线程。同时,主线程继续执行其他任务。

三、QThread 类的一些关键特性和用法

1、创建线程

         通过继承 QThread 类,可以创建一个自定义的线程类。在自定义的类中,可以重写 run() 函数,该函数定义了线程的执行体。

class MyThread : public QThread {
public:void run() override {// 线程的执行体}
};

2、启动线程

        使用 start() 函数来启动线程。一旦调用了 start()run() 函数将在新线程中执行。

MyThread thread;
thread.start();

3、等待线程结束

        使用 wait() 函数来等待线程执行结束。这确保主线程等待子线程完成后再继续执行。

thread.wait();

4、线程间通信

        Qt 提供了信号和槽机制,可以用于在线程之间进行安全的通信。在多线程中,使用信号和槽是一种避免共享资源问题的方式。

connect(sender, SIGNAL(sendMessage(QString)), receiver, SLOT(receiveMessage(QString)));

5、线程安全

  QThread 提供了一些方法来确保线程的安全性,如 mutexatomic 操作,以避免多线程竞争条件。

QMutex mutex;
mutex.lock();
// 线程安全的操作
mutex.unlock();

四、Qthread注意事项

        在使用 QThread 进行多线程编程时,有一些注意事项需要考虑,以确保正确、安全、高效地使用线程。以下是一些关键的注意事项:

1、不要直接调用 run 函数

        QThread 中的 run() 函数是线程执行体,但不应该直接调用它。正确的方式是通过 start() 函数启动线程,run() 函数会在新线程中自动执行。

// 错误的方式
MyThread thread;
thread.run(); // 不要这样调用// 正确的方式
MyThread thread;
thread.start(); // 通过 start 函数启动线程

2、避免直接继承 QThread

        直接继承 QThread 并重写 run() 函数是一种方式,但并不总是最好的。推荐使用组合的方式,将线程逻辑放在另外的类中,然后在 QThread 的子类中创建该类的实例。

class Worker : public QObject {Q_OBJECT
public slots:void doWork() {// 线程的执行体}
};class MyThread : public QThread {
public:void run() override {Worker worker;connect(this, &MyThread::startWork, &worker, &Worker::doWork);emit startWork();}signals:void startWork();
};

3、线程安全

        考虑多线程访问共享资源时的线程安全性。使用互斥锁 (QMutex) 或其他同步机制来确保对共享数据的访问是线程安全的。

QMutex mutex;
mutex.lock();
// 访问共享资源
mutex.unlock();

4、注意内存管理

        在多线程环境中,注意内存管理问题。确保在合适的时候释放线程中创建的资源,以避免内存泄漏。

5、合理设置线程属性

        使用 setObjectName() 为线程设置名称,以方便调试。可以使用 setPriority() 设置线程的优先级,但要注意过度使用优先级可能导致不稳定的行为。

MyThread thread;
thread.setObjectName("WorkerThread");
thread.setPriority(QThread::LowPriority);


6、不要在主线程中直接操作子线程的对象

        子线程的对象应该通过信号和槽来进行通信。在主线程中直接操作子线程的对象可能导致线程安全问题。

// 错误的方式
MyThread thread;
Worker worker;
worker.doWork(); // 避免在主线程中直接调用子线程对象的函数// 正确的方式
MyThread thread;
Worker worker;
connect(&thread, &MyThread::startWork, &worker, &Worker::doWork);
thread.start();

五、总结

        QThread 是 Qt 中处理多线程编程的基础,并提供了一些辅助工具和机制,以简化开发者在并发环境中的工作。但在某些情况下,使用 QtConcurrentQt Concurrent 命名空间中的高级功能可能更为方便。这些功能提供了更高层次的抽象,用于并发和并行处理。

        Qt C++ 提供了强大而灵活的多线程支持,使得多线程编程变得更加容易。通过 QThread 类的使用,开发者能够轻松创建和管理多线程应用。同时,信号和槽机制为线程间的通信提供了一种安全而高效的方式。

相关文章:

【QT学习十一】QThread

一、引言 在现代软件开发中&#xff0c;多线程编程变得越来越重要&#xff0c;尤其是对于需要处理并发任务的应用程序。Qt C 框架提供了强大的多线程支持&#xff0c;使得开发者能够轻松地创建和管理多线程应用。 在 Qt 中&#xff0c;多线程的实现主要基于 QThread 类。QThrea…...

Mybatis 39_使用MBG生成代码

此2个插件均未晚装成功!!!! 安装 MyBatipse插件 MyBatipse插件 - 开发MyBatis应用的Eclipse插件- 自动完成- 有效性验证- Mapper视图使用MBG MyBatis Generator (MBG):根据底层数据表来自动生成Mapper组件只要两步即可: (1) 提供一个简单的配置文件,告诉MBG连接数据…...

Hudi metadata table(元数据表)

什么是metadata表 Metadata表即Hudi元数据表,是一种特殊的Hudi表,对用户隐藏。该表用于存放普通Hudi表的元数据信息。Metadata表包含在普通Hudi表内部,与Hudi表是一一对应关系。 元数据表的作用 ApacheHudi元数据表可以显著提高查询的读/写性能。元数据表的主要目的是消…...

提高iOS App开发效率的方法

引言 随着智能手机的普及&#xff0c;iOS App开发成为越来越受欢迎的技术领域之一。许多人选择开发iOS应用程序来满足市场需求&#xff0c;但是iOS App开发需要掌握一些关键技术和工具&#xff0c;以提高开发效率和质量。本文将介绍一些关键点&#xff0c;可以帮助你进行高效的…...

MPU机制与实现详解

目录 MPU机制与实现详解 Partition元素-MPU Partition实现元素OSApplication Partition元素-RTE MPU机制与实现详解 1、freedom from interference 此概念来自ISO26262-1&#xff1a;多个元素之间没有可能导致违反安全目标的级联故障&#xff0c;称之为免于干涉。 在左侧的…...

pom文件冲突引起的Excel无法下载

问题一&#xff1a;之前生产环境上可以进行下载Excel的功能突然不能用了 报错提示信息&#xff1a; NoClassDefFoundError: Could not initialize class org.apache.poi.xssf.usermodel.XSSFWorkbook&#xff0c; 在最开始初始化的时候找不到对应的类&#xff0c;虽然我的Libr…...

【HarmonyOS4.0】第十篇-ArkUI布局容器组件(二)

三、层叠布局容器&#xff08;Stack&#xff09; 堆叠容器组件 Stack的布局方式是把子组件按照设置的对齐方式顺序依次堆叠&#xff0c;后一个子组件覆盖在前一个子组件上边。 注意&#xff1a;Stack 组件层叠式布局&#xff0c;尺寸较小的布局会有被遮挡的风险&#xff0c; …...

PLECS如何下载第三方库并导入MOSFET 的xml文件,xml库路径添加方法及相关问题

1. 首先xml库的下载&#xff0c;PLECS提供了一个跳转的链接。 https://www.plexim.com/download/thermal_models 2. 下载一个库&#xff08;以最后一个Wolfspeed为例&#xff0c;属于CREE的SiC MOSFET&#xff09; 下载这个就行&#xff0c;都包含了。不信自己可以试试再下载…...

使用emu8086实现——子程序的设计

一、实验目的 学习子程序的结构、特点&#xff0c;以及子程序的设计和调试方法 二、实验内容 1、从字符串中删除一个字符&#xff0c;并存储到寄存器AX中。 代码及注释&#xff1a; data segmentstring db exas ;字符串内容leng dw $-string ; 字符串长度key db x …...

快速排序、归并排序、希尔排序(2023-12-25)

参考文章 十大经典排序算法总结整理_十大排序算法-CSDN博客 推荐文章 算法&#xff1a;归并排序和快排的区别_归并排序和快速排序的区别-CSDN博客 package com.tarena.test.B20; import java.util.Arrays; import java.util.StringJoiner; public class B25 { static i…...

Qt SDL2播放Wav音频

这里介绍两种方法来实现Qt播放Wav音频数据。 方法一&#xff1a;使用QAudioOutput pro文件中加入multimedia模块。 #include <QApplication> #include <QFile> #include <QAudioFormat> #include <QAudioOutput>int main(int argc, char *argv[]) {…...

[ACM学习] 动态规划基础之一二三维dp

课内学习的动态规划 有记忆的迭代 优化解的结构&#xff1a;原始问题的一部分解是子问题的解 三要素&#xff1a;1.子问题 2.状态的定义 3.状态转移方程 定义 线性dp的一道例题 dp[i]表示以位置 i 结尾的方案总数&#xff0c;dp[4]2&#xff0c;因为&#xff1a;首先只放一…...

Qt点击按钮在其附近弹出一个窗口

效果 FS_PopupWidget.h #ifndef FS_POPUPWIDGET_H #define FS_POPUPWIDGET_H#pragma once#include <QToolButton> #include <QWidgetAction> #include <QPointer>class QMenu;class FS_PopupWidget : public QToolButton {Q_OBJECTpublic:FS_PopupWidget(QW…...

Springboot注解@Configuration和@Bean注解作用,生命周期

简介&#xff1a; Configuration 类是定义 bean 配置的地方&#xff0c;而 Bean 方法是具体创建 bean 实例的方法。 Configuration 作用&#xff1a; Configuration 注解用于定义配置类&#xff0c;表明该类包含一个或多个 bean 定义的方法。Spring 容器在启动时会自动扫描这些…...

30天精通Nodejs--第十五天:Websocket

引言 这里我们将继续深入探讨另一项强大且实时性极高的网络通信技术——WebSocket。通过本篇文章,将全面了解如何在Node.js环境中利用WebSocket实现服务端与客户端之间双向、低延迟的数据传输,并掌握其基础用法以及一些高级应用场景。 基础用法 安装WebSocket库 在Node.j…...

C++深入学习之STL:2、适配器、迭代器与算法部分

适配器概述 C标准模板库(STL)中提供了几种适配器&#xff0c;这些适配器主要用于修改或扩展容器类的功能。STL中的适配器主要包括以下几种&#xff1a; 1、迭代器适配器&#xff1a;迭代器适配器提供了一种机制&#xff0c;可以将非迭代器对象转换为迭代器对象。比如back_ins…...

Tiktok/抖音旋转验证码识别

一、引言 在数字世界的飞速发展中&#xff0c;安全防护成为了一个不容忽视的课题。Tiktok/抖音&#xff0c;作为全球最大的短视频平台之一&#xff0c;每天都有数以亿计的用户活跃在其平台上。为了保护用户的账号安全&#xff0c;Tiktok/抖音引入了一种名为“旋转验证码”的安…...

【Java 设计模式】设计原则

文章目录 ✨单一职责原则&#xff08;SRP&#xff09;✨开放/封闭原则&#xff08;OCP&#xff09;✨里氏替换原则&#xff08;LSP&#xff09;✨依赖倒置原则&#xff08;DIP&#xff09;✨接口隔离原则&#xff08;ISP&#xff09;✨合成/聚合复用原则&#xff08;CARP&#…...

Druid连接池工具公式化SQL附踩坑记录

1. 需求 使用Druid连接池工具格式化sql用于回显时候美观展示 2. 代码示例 2.1 依赖 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.6</version> </dependency> 2.2 ParseUtils…...

Linux内核--网络协议栈(二)UDP数据包发送

目录 一、引言 二、数据包发送 ------>2.1、数据发送流程 三、协议层注册 ------>3.1、socket系统调用 ------>3.2、socket创建 ------>3.3、协议族初始化 ------>3.4、对应协议的socket创建 ------>3.5、协议注册 四、通过套接字发送网络数据 --…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...