Qt系统相关——QThread

devtools/2024/9/24 3:42:05/

文章目录

    • QThread的API
    • 使用示例
    • 客户端多线程应用场景
    • 互斥锁
      • QMutex
      • QMutexLocker
      • QReadWriteLocker、QReadLocker、QWriteLocker
    • 条件变量和信号量

QThread的API

Qt中的多线程和Linux中的线程,本质上是一个东西

Linux线程概念

Linux多线程——线程控制

Linux多线程——互斥锁

Linux多线程——生产消费者模型

QThread:

  • 要创建线程,需要创建这个类的实例
  • 创建线程时,需指明线程入口函数
  • 创建QThread的子类,重写了其中的run方法,起到指定入口函数的方式(多态)

Tips:

这种方式在C++中并不常见,相比之下std::thread直接指定回调方式更常见

因为C++比较追求性能,多态机制可能导致运行时的额外开销(查询函数表,找到对应执行函数再执行)

但是对应客户端开发,对性能的要求,并没有那么的高

API说明
run()线程入口函数
start()通过运行run()开始执行线程
(该操作是真正调用系统API创建线程)
currentThread()获取当前线程的指针
isRunning()如果线程正在运行返回true,否则返回false
sleep()、msleep()、usleep()线程休眠,单位秒/毫秒/微妙
wait()线程阻塞,功能和pthread_join类似
terminate()终止线程执行。
线程可以立即终止,也可以不终止,取决于操作系统的调用
finished()线程结束发出的信号,可通过该信号实现线程的清理工作

使用示例

基于定时器的倒计时程序

创建QThread子类:

image-20240923211212409

thread.h

#ifndef THREAD_H
#define THREAD_H#include <QWidget>
#include<QThread>
class Thread : public QThread
{Q_OBJECT
public:Thread();//重写父类run方法void run();
signals://只需写函数声明, 定义Qt自动生成void notify();
};#endif // THREAD_H

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include"thread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void handle();private:Ui::Widget *ui;Thread thread;
};
#endif // WIDGET_H

thread.cpp

#include "thread.h"Thread::Thread()
{}void Thread::run()
{//针对时间进行计时,每过一秒,通过信号槽通知主线程更新界面for(int i = 0; i < 10; i++){sleep(1);//发生信息emit notify();}
}

widget.cpp

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//连接信号槽connect(&thread, &Thread::notify, this, &Widget::handle);//启动线程thread.start();
}Widget::~Widget()
{delete ui;
}void Widget::handle()
{int value = ui->lcdNumber->intValue();value--;ui->lcdNumber->display(value);
}

如果多个线程同时对界面进行修改,就会导致界面出错。

Qt直接一刀切,针对控件的任何修改,都在主线程中执行。

运行示意图:

image-20240923212827943

客户端多线程应用场景

在服务器开发的角度,多线程主要是充分利用多核CPU的计算资源,达到更高的效率。

而对于客户端,对效率要求并不是特别高,如果追求效率,把CPU计算资源吃完,会导致系统卡顿,这用户体验是很差的。

在客户端中,多线程主要是用于一些耗时的等待IO的操作,避免主线程卡死。

比如说客户端向服务端上传/下载较大的文件

这种密集的IO操作会使程序被系统阻塞挂起,一旦进程被挂起了,此时用户的操作就无法响应了。

因此使用单独的线程来处理这种密集的IO操作,就算挂起,也是挂起的这个线程,并不会影响主线程。

互斥锁

QMutex

谈到线程,必定绕不开线程安全问题,最通用的手段就是加锁,QMutex类就是Qt封装的互斥锁。

image-20240923215302391

上面这种情况就是线程安全问题,采取加锁,让线程串行执行

锁也是公共区的,只有一把锁

image-20240923215537861

QMutexLocker

C++11引入了std::lock_guard,智能锁RAII机制,这样能避免抛出异常或者忘记释放锁导致的问题。

Qt参考过来了,叫做QMutexLocker

image-20240923220111369

Tips:

Qt的锁和C++的锁,本质上都是封装系统提供的锁

虽然可以用C++的锁锁住Qt的线程,但是不建议。

QReadWriteLocker、QReadLocker、QWriteLocker

  • QReadWriteLocker读写锁,用于控制读和写的并发访问
  • QReadLocker用于读操作上锁,允许多个线程共享资源
  • QWriteLocker用于写操作上锁,一次允许一个线程写数据

条件变量和信号量

Qt当中的条件变量和信号量,与Linux当中的概念一模一样,只不过是接口不一样而已。

多个线程的调度是无序的,为了一定程度干预执行顺序,引入条件变量。

QWaitCondition

  • wait等待
  • wake唤醒
  • wakeAll唤醒全部

QSemaphore

  • acquire获取信号量
  • release释放信号量

http://www.ppmy.cn/devtools/116304.html

相关文章

《CUDA编程》1.GPU硬件与CUDA环境搭建

1 GPU 介绍 GPU&#xff08;graphics processing unit&#xff09;&#xff0c;意为图形处理器&#xff0c;也被称为显卡&#xff08;graphics card&#xff09;。GPU的浮点数运算峰值就比同时期的CPU高一个量级&#xff1b;GPU的内存带宽峰值也比同时期的CPU高一个量级。 CP…

weblogic CVE-2018-2894 靶场攻略

漏洞描述 Weblogic Web Service Test Page中⼀处任意⽂件上传漏洞&#xff0c;Web Service Test Page 在 "⽣产模式"下默认不开启&#xff0c;所以该漏洞有⼀定限制。 漏洞版本 weblogic 10.3.6.0 weblogic 12.1.3.0 weblogic 12.2.1.2 28 weblogic 12.2.1.3 …

Spring(四)多线程+异步任务执行服务+常见的Enable注解+SpringUnit测试

Spring多线程 Spring通过任务执行器&#xff08;TaskExecutor&#xff09;来实现多线程和并发编程ThreadPoolTaskExecutor实现一个基于线程池的TaskExecutor配置类中EnableAsync开启对异步任务的支持使用Async声明该任务为异步 ①、配置类 Configuration ComponentScan(&quo…

CVC输入语言

声明 位向量表达式&#xff08;或项&#xff09;由位向量常数、位向量变量以及下列函数构成。在STP中&#xff0c;所有变量必须在使用前声明。声明一个长度为32的位向量变量的例子是&#xff1a;x : BITVECTOR(32);。声明数组的例子如下&#xff1a; x_arr : ARRAY BITVECTOR(…

文本分类实战项目:如何使用NLP构建情感分析模型

文本分类实战项目&#xff1a;如何使用NLP构建情感分析模型 一、引言 随着互联网的迅速发展&#xff0c;用户在社交媒体、产品评论、论坛等平台上产生了大量的文本数据。通过分析这些数据&#xff0c;我们可以了解用户的情绪和态度&#xff0c;而情感分析就是专门用于分析文本…

伦敦金的交易差价意味着什么?

在伦敦金投资市场上&#xff0c;点差是指交易平台的买入价&#xff08;买价&#xff09;和卖出价&#xff08;卖价&#xff09;之间的差额。对投资者来说&#xff0c;点差是交易成本的一部分&#xff0c;但它是经纪商的收入来源。点差代表伦敦金投资者在进入和退出交易时需要支…

C#基础(13)结构体

前言 随着函数的讲解完成&#xff0c;我想你已经初步有了写一些复杂逻辑功能的能力&#xff0c;但是我们会发现其实在我们大部分实际开发情况中&#xff0c;很多我们需要写的变量可能不只有一个属性。 他可能有很多变量&#xff0c;那这时候我们如果要把这些变量集中到一个东…

LabVIEW提高开发效率技巧----使用LabVIEW工具

LabVIEW为开发者提供了多种工具和功能&#xff0c;不仅提高工作效率&#xff0c;还能确保项目的质量和可维护性。以下详细介绍几种关键工具&#xff0c;并结合实际案例说明它们的应用。 1. VI Analyzer&#xff1a;自动检查代码质量 VI Analyzer 是LabVIEW提供的一款强大的工…