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

Qthread应用

前言

重新学习qthread,有一个任务,我们要交给子线程运行,把结果传到主线程,那我们只需要将任务类继承Qthread,重写run函数,在里面写运行逻辑,当主线程需要它运行的时候就会触发start开始子线程,这就是多线程的核心思想。

这里我设计了一个程序,有三个部分,第一个部分lsw1是一个listwidget,显示生成的随机数,第二个显示冒泡排序的结果,第三个生成快速排序的结果,ui如下:

界面搭建就不用讲了,接下来讲讲功能的实现。

为什么采用多线程

大家都知道采用多线程的时候程序运行快,界面不容易出现卡顿,当数据量大的时候,如果在主线程里面执行,他会阻塞主线程的ui刷新造成卡顿现象,就需要把这些事务处理放到子线程里面,主线程只负责ui的更新。

随机数生成

经过上面的讲述,我们随机数生成可以放在一个专门的线程,类命名为Generat,继承Qthread,除了需要重写run函数,我们需要从主线程接受需要生成多少个随机数这样的一个函数

//将主线程中接受的数据赋值给m_numvoid recnum(int num);

m_num是这个类的成员函数,还需要在我们排序执行完了以后,需要有一个信号,把执行结果传递给主线程,他们之间用connect的Qt::QueuedConnection模式进行通讯 ,和运行了多久的计时器时间也要通过信号传递

//生成的序列发送信号void sendarray(QVector<int> num);//发送用时void sendtime(int time);

计时器的选用

计时器采用的是QElapsedTimer类,这是一个毫秒级的计时器,当程序运行过快的时候,会出现一个问题,比如运行时间只有1ms,太小了,他就会为0,碰到这种情况有两个解决办法

1.增加数据量,延长程序的运行时间

2.采用精度更高的计时器

run函数实现

 随机数刷新用到了QRandomGenerator类,先上我使用的方法

for (int i = 0; i < m_num; ++i) {list.push_back(QRandomGenerator::global()->bounded(0,10000));}

该类下global是一个随机数生成器,bounded限制他的生成范围,第一个参数是最小值,第二个参数是最大值。

类整体展示

//mytread.h
//生成随机数的线程类
class Generate:public QThread
{Q_OBJECT
public:Generate(QObject *parent=nullptr);//将主线程中接受的数据赋值给m_numvoid recnum(int num);// QThread interface
private:int m_num;protected:void run() override;signals://生成的序列发送信号void sendarray(QVector<int> num);//发送用时void sendtime(int time);//随机数生成完毕,通知排序工作线程开始工作void startsort();
};
//mythread.cpp
void Generate::recnum(int num)
{m_num=num;
}//生成随机数线程
void Generate::run()
{QVector<int>list;QElapsedTimer timer;timer.start();for (int i = 0; i < m_num; ++i) {list.push_back(QRandomGenerator::global()->bounded(0,10000));}int milsec=timer.elapsed();emit sendarray(list);emit sendtime(milsec);emit startsort();
}

有一个信号是后面加的start sort,在他的下一级还有两个工作线程,他相当于是个生产者,生产好了以后通知消费者开始用这些数据工作。

这样线程类就做好了,在主程序中做好connect接收子线程的信号传递的数据,在ui上显示就行了。

信号的处理绑定

主线程中首先把子线程类的对象new出来

Generate *gen=new Generate;

主程序有一个starting信号,负责把生成多少个随机数发送给子线程,子线程的recnum函数就会接收处理,当界面的按钮点击了以后,就会发送starting信号,并启动随机数线程

//通过信号将要创建多少个随机数传递给子线程connect(this,&MainWindow::starting,gen,&Generate::recnum,Qt::QueuedConnection);//点击按钮后执行子线程connect(ui->pushButton,&QPushButton::clicked,this,[=](){emit starting(10000);gen->start();});

冒泡排序线程

线程的设计和上面差不多,不过他没有下级线程要通知,随机数线程生成了随机数数组后会有个信号传递数组,我们冒泡的线程也接收一份,进行排序逻辑处理

void Bubblesort::run()
{QElapsedTimer time;//采用秒级计时器,如果数据太少执行太快会导致运行时间太短显示运行0秒time.start();int temp;//升序冒泡for (int i = 0; i < m_num.size(); ++i) {for (int j = 0; j < m_num.size()-i-1; ++j) {if(m_num.at(j)>m_num.at(j+1)){temp=m_num.at(j);m_num[j]=m_num[j+1];m_num[j+1]=temp;}}}int sec=time.elapsed();emit sendarray(m_num);//发送排序后的数组emit sendtime(sec);//发送时间
}

 快速排序线程

同上,逻辑:

//快速排序实现
void Quicksort::quicksort(QVector<int> &arr, int left, int right)
{if (left >= right) return;int i = left;int j = right;// 取中间值作为基准,避免最坏情况int pivot = arr[(left + right) / 2];while (i <= j) {while (arr[i] < pivot) i++;  // 找左边大于等于基准的while (arr[j] > pivot) j--;  // 找右边小于等于基准的if (i <= j) {// 交换元素std::swap(arr[i], arr[j]);i++;j--;}}// 递归排序子数组quicksort(arr, left, j);quicksort(arr, i, right);
}void Quicksort::run()
{QElapsedTimer time;time.start();quicksort(m_num,0,m_num.size()-1);int sec=time.elapsed();emit sendarray(m_num);//发送数组emit sendtime(sec);//发送时间
}

效果 

剩余的就是在主线程做一些信号绑定就行了,运行效果如下:

由此看到,当遇到数据量比较大的时候,冒泡排序是非常慢的,如果放到主线程跑,ui这段时间内都废了,十分影响使用体验。 

http://www.lqws.cn/news/468505.html

相关文章:

  • Taro 跨端应用性能优化全攻略:从原理到实践
  • verilog HDLBits刷题“Module addsub”--模块 addsub---加法器-减法器
  • leetcode 3085. 成为 K 特殊字符串需要删除的最少字符数 中等
  • 实现自动化资源调度与弹性伸缩
  • AWS RDS/Aurora 开启 Database Insights 高级模式全攻略
  • Android 终端模拟器 termux app
  • C++ 第一阶段项目二:温度转换工具
  • ubuntu24.4 + ros2 jazzy 安装gazebo
  • 冰箱压缩机电机驱动板【IPM部分】
  • 【StarRocks系列】建表优化
  • Kettle数据抽取(五)转换控件
  • 《map和set的使用介绍》
  • C#测试调用ClosedXML根据批注设置excel单元格内容
  • 细节/数学/滑动窗口
  • Nginx+tomcat集群
  • 多头注意力机制中全连接函数
  • 成长笔记——多串口发送与接收
  • 面试题-函数类型的重载是啥意思
  • Qt + C++ 入门2(界面的知识点)
  • 吐槽之前后端合作开发
  • FastAPI框架的10个重要知识点总结
  • Typora文档另存与图片迁移的一种思路
  • VR飞夺泸定桥沉浸式历史再现​
  • [C++] STL数据结构小结
  • Linux - 安装 git(sudo apt-get)
  • WPF Style样式 全局样式资源字典
  • Qt/C++应用:防御性编程完全指南
  • leetcode332.重新安排行程:优先队列与DFS实现欧拉路径的行程规划
  • 【智能体】n8n聊天获取链接后爬虫知乎
  • 108. 将有序数组转换为二叉搜索树