Qt开发-----线程调度

news2024/11/29 4:40:50

 目录

 前言

一、Linux下查看进程的情况

二、线程的创建

三、多线程的创建和使用


 前言

以下引用内容源自正点原子Qt开发指南文档。

        我们写的一个应用程序,应用程序跑起来后一般情况下只有一个线程,但是可能也有特殊情况。比如我们前面章节写的例程都跑起来后只有一个线程,就是程序的主线程。线程内的操作都是顺序执行的。恩,顺序执行?试着想一下,我们的程序顺序执行,假设我们的用户界面点击有某个操作是比较耗时的。您会发现界面点击完了,点击界面对应的操作还没有完成,所以就会冻结界面,不能响应,直到操作完成后,才返回到正常的界面里。如果我们的界面是这么设计的话,估计用户得发毛了。
        这种情况我们一般是创建一个单独的线程来执行这个比较耗时的操作。比如我们使用摄像头拍照保存照片。恩,很多朋友问,这个不算耗时吧。对的在电脑上使用 Qt 拍照,处理起来非常快。根本也不需要开启一个线程来做这种事。但是我们是否考虑在嵌入式的 CPU 上做这种事情呢?嵌入式的 CPU 大多数都没有电脑里的 CPU 主频(几 GHz)那么高,处理速度也不快。此时我们就需要考虑开多一个线程来拍照了。拍完照再与主线程(主线程即程序原来的线程)处理好照片的数据,就完成了一个多线程的应用程序了。
        官方文档里说,QThread 类提供了一种独立于平台的方法来管理线程。QThread 对象在程序中管理一个控制线程。QThreads 在 run()中开始执行。默认情况下,run()通过调用 exec()来启动事件循环,并在线程中运行 Qt 事件循环。您可以通过使用 QObject::moveToThread()将 worker对象移动到线程来使用它们。QThread 线程类是实现多线程的核心类。Qt 有两种多线程的方法,其中一种是继承 QThread的 run()函数,另外一种是把一个继承于 QObject 的类转移到一个 Thread 里。Qt4.8 之前都是使用继承 QThread 的 run()这种方法,但Qt4.8 之后,Qt 官方建议使用第二种方法。两种方法区别不大,用起来都比较方便,但继承 QObject 的方法更加灵活。所以 Qt 的帮助文档里给的参考是先给继承 QObject 的类,然后再给继承 QThread 的类。

一、Linux下查看进程的情况

  • 进程 (Process)

    • 进程是操作系统中资源分配的基本单位,代表一个正在执行的程序。每个进程都有自己的内存空间、系统资源(如文件描述符)和运行状态。
    • 一个进程可以包含一个或多个线程。
  • 线程 (Thread)

    • 线程是进程中执行的最小单位。一个线程是一个轻量级的执行单元,多个线程共享同一进程的内存空间和资源。
    • 线程之间的切换通常比进程切换更快,因为它们共享同一进程的上下文和资源,减少了上下文切换的开销。

总的来说,线程是CPU调度的最小单位,一个进程至少是有一个线程当然也可以有多个线程。这里打开你的命令行窗口( Ctrl+Alt+T),然后这里输入如下,查看当前系统的进程情况。

ps -aux

然后创建一个Qt项目,下面是这个按钮的槽函数,很显然当我们点击之后就会进到这个死循环里面去。

void Widget::on_pushButton_clicked()
{
    qDebug()<<"click"<<endl;
    while(1){

    }
    qDebug()<<"over"<<endl;
}

在你的Qtcreator去点击运行。

然后在命令行窗口输入:

ps -aux | grep QThread//QThread是Qt程序名字

 这条指令是查找名字为QThread的进程

这里就看到我这个进程的PID为8455,然后我要去查看这个进程下有哪些子进程。

ps -m 8455

ps -m 是 Linux 中用于显示当前进程及其线程的命令。具体来说,它显示了与指定进程相关的线程的信息。这条命令可以帮助你查看进程的线程状态和相关信息。 

这里就可以看到这个Qt程序带有另外的五个子线程,第一个是表示主线程,剩下几个是这个进程的分支也就是子线程。

然后回到你的QTcreator,点击这个按钮,然后就是卡死的情况了,这个程序就阻塞了。

好了现在就要处理这个东西了,这里就可以去用线程来去处理。

二、线程的创建

class MyThread : public QThread{
    Q_OBJECT
public:
    MyThread(QWidget* parent=nullptr){
        Q_UNUSED(parent);
    }

    ~MyThread(){
        qDebug()<<"die"<<endl;
    }
    void run() override{
        qDebug()<<"start "<<endl;
        while(1){

        }
        deleteLater();
    }
};
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) //
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //sadasdw
    mythread= new MyThread(this);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
   mythread->start();
}

这里在Widget调用构造函数的时候就创建了这个线程,当我们去点击按钮的时候就是线程的开始。这里就可以实现不出现卡死,这就是线程的调度。

三、多线程的创建和使用

Widget.h代码:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QThread>
#include <QtDebug>
class MyThread;

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();
    void on_pushButton_2_clicked();

private:
    Ui::Widget *ui;
    MyThread* mythread;
};


class MyThread : public QThread{
    Q_OBJECT
public:
    MyThread(QWidget* parent=nullptr){
        Q_UNUSED(parent);
    }

    ~MyThread(){
        qDebug()<<"die"<<endl;
    }
    void run() override{
        qDebug()<<"start "<<endl;
        msleep(5000);

        qDebug()<<"over "<<endl;
        deleteLater();
    }
};

#endif // WIDGET_H

这里我有一个MyThread线程的类,这个类重写了父类run()方法,当线程开启的时候这个就会调用这个方法。当run方法执行到最后一行的时候要用deleteLater()来去把这个线程的对象删除掉,否则堆区的内存就会无法释放。

下面是Widget.cpp文件

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) //
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //sadasdw
    //mythread= new MyThread(this);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
  // mythread->start();
    MyThread *testThread = new MyThread(this);
    testThread->start();
}

这里就是点击一个按钮就会开启一个线程,每次点击之后都会去开启线程,这就是多线程的创建。

今日壁纸: 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2222183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《YOLO目标检测》—— YOLOv1 详细介绍

文章目录 一、算法特点二、网络结构三、检测过程四、损失函数五、性能表现六、优缺点 YOLO v1&#xff08;You Only Look Once version 1&#xff09;是一种快速的目标检测算法&#xff0c;以下是对YOLO v1的详细介绍&#xff1a; 一、算法特点 端到端的网络结构&#xff1a;Y…

项目:Boost 搜索引擎

项目&#xff1a;Boost 搜索引擎 1、项目背景 公司&#xff1a;百度、360、搜狗、谷歌 …站内搜索&#xff1a;搜索的数据更垂直&#xff08;相关&#xff09;&#xff0c;数据量小 2、整体框架 3、技术栈和项目环境 技术栈&#xff1a;C/C C11&#xff0c;STL&#xff0c;jso…

【JAVA毕设】基于JAVA的仓库管理系统

一、项目介绍 本系统前端框架采用了比较流行的渐进式JavaScript框架Vue.js。使用Vue-Router实现动态路由&#xff0c;Ajax实现前后端通信&#xff0c;Element-plus组件库使页面快速成型。后端部分&#xff1a;采用SpringBoot作为开发框架&#xff0c;同时集成MyBatis、Redis、…

C#中的LINQ之美:优雅的数据查询与操作

LINQ&#xff08;Language Integrated Query&#xff0c;语言集成查询&#xff09;是C#中一个强大的工具&#xff0c;它将查询功能直接融入到语言中&#xff0c;使开发者能够以一种更直观、更接近自然语言的方式来操作数据。LINQ不仅能极大地提高开发效率&#xff0c;而且让代码…

掌握ElasticSearch(五):查询和过滤器

一、查询和过滤器的区别 在 Elasticsearch 中&#xff0c;查询&#xff08;Query&#xff09;和过滤器&#xff08;Filter&#xff09;是用于检索和筛选数据的重要组成部分。它们虽然都能用来查找文档&#xff0c;但在性能和用法上有所不同。下面详细介绍查询和过滤器的概念以…

Lucas带你手撕机器学习——K近邻

K近邻 (K-Nearest Neighbor KNN) K近邻算法&#xff08;K-Nearest Neighbors, KNN&#xff09;是一种简单直观的机器学习算法&#xff0c;适用于分类和回归问题。它的核心思想是&#xff1a;判断一个数据点的类别或预测值时&#xff0c;参考它在特征空间中最近的 KKK 个数据点…

【2024】【字节青训营】:字节青训营入营测试题——Java版本(已提交通过)

目录 简单题目 计算x到y的最小步数 环状 DNA 序列的最小表示法 Base32 解码和编码 打点计时器 兔群繁殖之谜 完美整数 找出整数数组中占比超过 一半 的数 找出最长的神奇数列 找单独的数 字符串最短循环字串 二进制反码转换问题 中等题目 简单四则运算 数字翻译…

什么是微服务中的反应性扩展?

大家好&#xff0c;我是锋哥。今天分享关于【什么是微服务中的反应性扩展&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; 什么是微服务中的反应性扩展&#xff1f; Reactive Extensions 也称为 Rx。这是一种设计方法&#xff0c;我们通过调用多个服务来收集结果…

STM32G474使用TIM2触发DAC输出输出正弦波

STM32G474使用TIM2触发DAC输出&#xff0c;数据从内存到外设就要使用DMA来协助。DAC1每隔1秒输出一个正弦波数据&#xff0c;就会模拟近似得到模拟的正弦波形。用来测试CPU内部的运算放大器&#xff0c;或者用作其它模拟输入信号。 测试程序如下&#xff1a; #include "…

立志最细,FreeRtos的中断管理(Interrupt Management)函数,详解!!!

前言&#xff1a;本文参考&#xff0c;韦东山老师开发文档&#xff0c;连接放在最后。 为什么需要中断管理函数&#xff1f; 在FreeRtos操作系统中&#xff0c;需要实时响应性&#xff0c;也就是随时随地必须保证正常多任务的运行&#xff0c;如果有中断发生&#xff0c;因为中…

Spring Cloud --- Sentinel 规则持久化

为什么要持久化 一旦我们重启微服务应用&#xff0c;sentinel 规则将消失&#xff0c;生产环境需要将配置规则进行持久化 怎么实现持久化 将限流配置规则持久化进 Nacos 保存&#xff0c;只要刷新 8401 某个 rest 地址&#xff0c;sentinel 控制台的流控规则就能看到&#x…

keil新建工程HC32L176MATA

先看一下最后的文件夹结构&#xff08;文件夹结构可以根据项目实际的需要去定义&#xff09; keil内&#xff1a; 参考文章&#xff1a; KEIL平台下新建华大HC32F460单片机工程笔记_hc32f keil环境搭建-CSDN博客 &#xff08;我根据需要&#xff0c;创建的文件夹结构和原文是有…

面试总结一

面试总结 1、自我介绍一下自己2.面试11、css常用布局有哪些2、css常用的属性3.js原型链4、开发中遇到的技术难点5、闭包6、ts了解什么呢7.git都用什么命令8、vue怎么打包9.vue启动一个项目需要什么10、vue怎么创建一个项目 2.面试21.vue2和vue3有什么区别2.复杂组件的封装&…

C#,自动驾驶技术,ASAM OpenDRIVE BS 1.8.0 规范摘要与C# .NET Parser

本文介绍自动驾驶技术的标准之一《ASAM OpenDRIVE》1.8.0 版本的规范摘要&#xff0c;及北京联高软件开发有限公司实现的 C# 版本 xodr 文件&#xff08;XML&#xff09; Parser 源代码。 本文档是 ASAM e.V. 的版权财产。 在更改常规许可条款时&#xff0c;ASAM 允许不受限制地…

gateway 整合 spring security oauth2

微服务分布式认证授权方案 在分布式授权系统中&#xff0c;授权服务要独立成一个模块做统一授权&#xff0c;无论客户端是浏览器&#xff0c;app或者第三方&#xff0c;都会在授权服务中获取权限&#xff0c;并通过网关访问资源 OAuth2的四种授权模式 授权码模式 授权服务器将授…

【原创】统信UOS如何安装最新版Node.js(20.x)

注意直接使用sudo apt install nodejs命令安装十有八九会预装10.x的老旧版本Node.js&#xff0c;如果已经安装的建议删除后安装如下方法重装。 在统信UOS系统中更新Node.js可以通过以下步骤进行&#xff1a; 1. 卸载当前版本的Node.js 首先&#xff0c;如果系统中已经安装了N…

Maven进阶——坐标、依赖、仓库

目录 1.pomxml文件 2. 坐标 2.1 坐标的概念 2.2 坐标的意义 2.3 坐标的含义 2.4 自己项目的坐标 2.5 第三方项目坐标 3. 依赖 3.1 依赖的意义 3.2 依赖的使用 3.3 第三方依赖的查找方法 3.4 依赖范围 3.5 依赖传递和可选依赖 3.5.1 依赖传递 3.5.2 依赖范围对传…

推荐一个开源非线性视频编辑器:Kdenlive

Kdenlive是一个开源的视频编辑软件&#xff0c;项目始于约2003年。它基于Qt和KDE框架库构建&#xff0c;大部分视频处理由MLT框架完成&#xff0c;同时依赖其他开源项目如FFmpeg、frei0r、movit、ladspa、sox等。 软件特点&#xff1a; - 多轨视频编辑&#xff1a;支持多个音频…

大数据新视界 -- 大数据大厂之大数据和增强现实(AR)结合:创造沉浸式数据体验

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

2024 睿抗机器人开发者大赛(RAICOM)-【网络安全】CTF 部分WP

文章目录 一、前言二、MICS你是黑客么循环的压缩包Goodtime 三、WEBpy 四、Crypto变异凯撒RSAcrypto3 一、前言 WP不完整&#xff0c;仅供参考&#xff01; 除WEB&#xff0c;RE&#xff0c;PWN外&#xff0c;其余附件均已打包完毕 也是一个对MISC比较友好的一个比赛~ 123网…