# Qt 多线程
# 1, 构造函数
// 构造函数 | |
QThread::QThread(QObject *parent = Q_NULLPTR); | |
// 判断线程中的任务是不是处理完毕了 | |
bool QThread::isFinished() const; | |
// 判断子线程是不是在执行任务 | |
bool QThread::isRunning() const; | |
// Qt 中的线程可以设置优先级 | |
// 得到当前线程的优先级 | |
Priority QThread::priority() const; | |
void QThread::setPriority(Priority priority); | |
优先级: | |
QThread::IdlePriority --> 最低的优先级 | |
QThread::LowestPriority | |
QThread::LowPriority | |
QThread::NormalPriority | |
QThread::HighPriority | |
QThread::HighestPriority | |
QThread::TimeCriticalPriority --> 最高的优先级 | |
QThread::InheritPriority --> 子线程和其父线程的优先级相同, 默认是这个 | |
// 退出线程,停止底层的事件循环 | |
// 退出线程的工作函数 | |
oid QThread::exit(int returnCode = 0); | |
// 调用线程退出函数之后,线程不会马上退出因为当前任务有可能还没有完成,调回用这个函数是 | |
// 等待任务完成,然后退出线程,一般情况下会在 exit () 后边调用这个函数 | |
bool QThread::wait(unsigned long time = ULONG_MAX); |
# 信号槽
// 和调用 exit () 效果是一样的 | |
[slot] void QThread::quit(); | |
// 启动子线程 | |
[slot] void QThread::start(Priority priority = InheritPriority); | |
// 线程中执行的任务完成了,发出该信号 | |
// 任务函数中的处理逻辑执行完毕了 | |
[signal] void QThread::finished(); | |
// 开始工作之前发出这个信号,一般不使用 | |
[signal] void QThread::started(); |
# 静态函数
// 返回一个指向管理当前执行线程的 QThread 的指针 | |
[static] QThread *QThread::currentThread(); | |
// 返回可以在系统上运行的理想线程数 == 和当前电脑的 CPU 核心数相同 | |
[static] int QThread::idealThreadCount(); | |
// 线程休眠函数 | |
[static] void QThread::msleep(unsigned long msecs); // 单位:毫秒 | |
[static] void QThread::sleep(unsigned long secs); // 单位:秒 | |
[static] void QThread::usleep(unsigned long usecs); // 单位:微秒 |
# 任务处理
// 子线程要处理什么任务,需要写到 run () 中 | |
[virtual protected] void QThread::run(); |
# 2, 任务对象移动到主线程
# 线程头文件
#ifndef MYTHREAD_H | |
#define MYTHREAD_H | |
#include <QObject> | |
#include <QVector> | |
// 创建的子线程,生成随机数 | |
class Generate : public QObject | |
{ | |
Q_OBJECT | |
public: | |
explicit Generate(QObject *parent = nullptr); | |
// 接受主线程传过来的参数,随机数 num | |
// 子线程运行函数,第二种方法可以直接将 num 作为参数传入 | |
void working(int num); | |
signals: | |
// 使用信号槽将数据传递给主线程,界面操作只能由主线程来进行 | |
void sendArray(QVector<int> num); | |
public slots: | |
}; | |
// 冒泡排序 | |
class BubbleSort : public QObject | |
{ | |
Q_OBJECT | |
public: | |
explicit BubbleSort(QObject *parent = nullptr); | |
// 子线程运行函数 | |
void working(QVector<int> list); | |
signals: | |
// 使用信号槽将数据传递给主线程,界面操作只能由主线程来进行 | |
// 发送的有序数组 | |
void finish(QVector<int> list); | |
public slots: | |
}; | |
// 快速排序 | |
class QuickSort : public QObject | |
{ | |
Q_OBJECT | |
public: | |
explicit QuickSort(QObject *parent = nullptr); | |
// 子线程运行函数 | |
void working(QVector<int> list); | |
signals: | |
// 使用信号槽将数据传递给主线程,界面操作只能由主线程来进行 | |
void finish(QVector<int> list); | |
public slots: | |
private: | |
// 实现快速排序算法 | |
// 容器,起始位置,结束位置 | |
void quickSort(QVector<int> &list,int l,int r); | |
}; | |
#endif // MYTHREAD_H |
# 线程实现
#include "mythread.h" | |
#include <QElapsedTimer> // 记录时间 | |
#include <QtDebug> | |
#include <QThread> | |
Generate::Generate(QObject *parent) : QObject(parent) | |
{ | |
} | |
void Generate::working(int num) | |
{ | |
qDebug()<< "生成随机数的线程地址" <<QThread::currentThread(); | |
// 存放随机数 vector 容器 | |
QVector<int> list; // 子线程生成数据,要通过传递给主线程 | |
QElapsedTimer time; | |
time.start();// 开始记录 | |
for (int i = 0;i <num;++i) | |
{ | |
// 从尾部插入 | |
list.push_back(qrand()%100000); | |
} | |
qint64 milsec = time.elapsed(); // 毫秒 | |
qDebug()<< "生成" <<num << "个随机总数用时"<<milsec<<"毫秒"; | |
// 发送给主线程 | |
emit sendArray(list); // 将数据发给主线程 | |
} | |
// 冒泡排序,补齐 parent | |
BubbleSort::BubbleSort(QObject *parent) : QObject(parent) | |
{ | |
} | |
// 实现冒泡排序,实现相邻两个元素的交换 | |
void BubbleSort::working(QVector<int> list) | |
{ | |
qDebug()<< "冒泡排序的线程地址" <<QThread::currentThread(); | |
// 存放随机数 vector 容器 | |
QElapsedTimer time; | |
time.start(); | |
int temp; | |
for(int i = 0;i<list.size();++i) | |
{ | |
for(int j =0;j<list.size()-i-1;++j) // 从后数往前比较 | |
{ | |
if(list[j]>list[j+1]) | |
{ | |
temp = list[j]; | |
list[j] = list[j+1]; | |
list[j+1]=temp; | |
} | |
} | |
} | |
qint64 milsec = time.elapsed(); | |
qDebug()<< "冒泡排序用时" <<milsec<<"毫秒"; | |
// 发送给主线程 | |
emit finish(list); // 将数据发给主线程 | |
} | |
// 快速,补齐 parent | |
QuickSort::QuickSort(QObject *parent) : QObject(parent) | |
{ | |
} | |
// 实现快速排序 | |
void QuickSort::working(QVector<int> list) | |
{ | |
qDebug()<< "快速排序的线程地址" <<QThread::currentThread(); | |
// 存放随机数 vector 容器 | |
QElapsedTimer time; | |
time.start(); | |
// 快速排序算法 | |
quickSort(list,0,list.size()-1); | |
qint64 milsec = time.elapsed(); | |
qDebug()<< "快速排序用时" <<milsec<<"毫秒"; | |
// 发送给主线程 | |
emit finish(list); // 将数据发给主线程 | |
} | |
// 快排算法 | |
void QuickSort::quickSort(QVector<int> &s, int l, int r) | |
{ | |
if(l < r) | |
{ | |
int i = l,j=r; | |
// 拿出第一个元素,保存到 x 中,第一个位置为空 | |
int x = s[l]; | |
while (i < j) | |
{ | |
// 从右向左找小于 x 的数 | |
while (i < j && s[j] >= x) | |
{ | |
// 左移,直到遇到小于等于 x 的数 | |
j--; | |
} | |
if (i < j) | |
{ | |
// 将右侧找到的小于 x 的元素放入左侧坑中,右侧出现一个坑 | |
// 左侧元素索引后移 | |
s[i++] = s[j]; | |
} | |
// 从左向右找大于等于 x 的数 | |
while (i < j && s[i] < x) | |
{ | |
// 右移,直到遇到大于 x 的数 | |
i++; | |
} | |
if (i < j) | |
{ | |
// 将左侧找到的元素放入右侧坑中,左侧出现一个坑 | |
// 右侧元素索引向前移动 | |
s[j--] = s[i]; | |
} | |
} | |
// 此时 i=j, 将保存在 x 中的数填入坑中 | |
s[i] = x; | |
quickSort(s, l, i - 1); // 递归调用 | |
quickSort(s, i + 1, r); | |
} | |
} |
# 线程调用
#include "mainwindow.h" | |
#include "ui_mainwindow.h" | |
#include "mythread.h" | |
#include <QThread> | |
MainWindow::MainWindow(QWidget *parent) : | |
QMainWindow(parent), | |
ui(new Ui::MainWindow) | |
{ | |
ui->setupUi(this); | |
// 当运行,用户点击按钮,就要调用子线程生成随机数,传递给主线程 | |
//1, 创建子线程对象, | |
// QThread* t1 = new QThread (this); // 添加之后会析构申请的空间 | |
// QThread* t2 = new QThread(this); | |
// QThread* t3 = new QThread(this); | |
QThread* t1 = new QThread; | |
QThread* t2 = new QThread; | |
QThread* t3 = new QThread; | |
//2, 创建任务类的对象 | |
Generate* gen = new Generate; | |
BubbleSort * bubble = new BubbleSort; | |
QuickSort * quick = new QuickSort; | |
//3, 将任务对象移动到某个子线程中 | |
gen->moveToThread(t1); // 生成随机数 | |
bubble->moveToThread(t2); | |
quick->moveToThread(t3); | |
// 信号和槽,主函数将 starting 的数,传递给子线程的 recNum 用户接受数量 | |
connect(this,&MainWindow::starting,gen,&Generate::working); | |
// 启动子线程,使用信号与槽,当用户点击 | |
connect(ui->start,&QPushButton::clicked,this,[=]() | |
{ | |
emit starting(10000); | |
// 给子线程发送信号 | |
t1->start(); // 调用子线程运行方法,还没有执行 | |
}); | |
// 当有了随机数之后,开始起痘冒泡和快速排序线程 | |
// 在排序之前,线程要先拿到所需要的数据 | |
connect(gen,&Generate::sendArray,bubble,&BubbleSort::working); | |
connect(gen,&Generate::sendArray,quick,&QuickSort::working); | |
// 添加 connect 用于接受子线程传过来的 list 容器随机数 | |
// 连接子线程,但子线程信号 sendArray 运行时,主线程接受 | |
connect(gen,&Generate::sendArray,this,[=](QVector <int> list) | |
{ | |
// | |
// 主线程开始接受来自子线程发送过来的 list,于此同时子线程开始运行 | |
t2->start(); | |
t3->start(); | |
for(int i =0;i<list.size();i++) | |
{ | |
ui->randlist->addItem(QString::number(list.at(i))); | |
} | |
}); | |
// 排序运行之后,将排序好的数据放到主线程 | |
connect(bubble,&BubbleSort::finish,this,[=](QVector<int> list) | |
{ | |
for(int i =0;i<list.size();++i) | |
{ | |
ui->bubblelist->addItem(QString::number(list.at(i))); | |
} | |
}); | |
connect(quick,&QuickSort::finish,this,[=](QVector<int> list) | |
{ | |
for(int i =0;i<list.size();++i) | |
{ | |
ui->quicklist->addItem(QString::number(list.at(i))); | |
} | |
}); | |
// 手写销毁资源 | |
connect(this,&MainWindow::destroy,this,[=]() | |
{ | |
t1->quit(); | |
t1->wait(); | |
t1->deleteLater(); // 释放空间 | |
t2->quit(); | |
t2->wait(); | |
t2->deleteLater(); // 释放空间 | |
t3->quit(); | |
t3->wait(); | |
t3->deleteLater(); // 释放空间 | |
gen->deleteLater(); | |
bubble->deleteLater(); | |
quick->deleteLater(); | |
}); | |
} | |
MainWindow::~MainWindow() | |
{ | |
delete ui; | |
} |
# 3, 线程池
创建子线程
- 引用头文件
#include <QRunnable> | |
#include <QVector> | |
#include <QObject> |
# 头文件
// 创建的子线程,生成随机数 | |
class Generate : public QObject, public QRunnable | |
{ | |
Q_OBJECT | |
public: | |
explicit Generate(QObject *parent = nullptr); | |
// 接受主线程传过来的参数,随机数 num | |
void recNum(int num); | |
// 子线程运行函数 | |
void run() override; | |
signals: | |
// 使用信号槽将数据传递给主线程,界面操作只能由主线程来进行 | |
void sendArray(QVector<int> num); | |
public slots: | |
private: | |
// 设置信号槽接受主线程传过来的数据 | |
int m_num; | |
}; | |
// 冒泡排序 | |
class BubbleSort : public QObject, public QRunnable | |
{ | |
Q_OBJECT | |
public: | |
explicit BubbleSort(QObject *parent = nullptr); | |
// 接受主线程传过来的参数,数组 | |
void recArray(QVector<int> list); | |
// 子线程运行函数 | |
void run() override; | |
signals: | |
// 使用信号槽将数据传递给主线程,界面操作只能由主线程来进行 | |
// 发送的有序数组 | |
void finish(QVector<int> list); | |
public slots: | |
private: | |
// 设置信号槽接受主线程传过来的数据 | |
QVector<int> m_list; | |
}; | |
// 快速排序 | |
class QuickSort : public QObject, public QRunnable | |
{ | |
Q_OBJECT | |
public: | |
explicit QuickSort(QObject *parent = nullptr); | |
// 接受主线程传过来的参数,随机数 num | |
void recArray(QVector<int> list); | |
// 子线程运行函数 | |
void run() override; | |
signals: | |
// 使用信号槽将数据传递给主线程,界面操作只能由主线程来进行 | |
void finish(QVector<int> list); | |
private: | |
// 设置信号槽接受主线程传过来的数据 | |
QVector<int> m_list; | |
// 实现快速排序算法 | |
// 容器,起始位置,结束位置 | |
void quickSort(QVector<int> &list,int l,int r); | |
}; |
# 函数实现
#include "mythread.h" | |
#include <QElapsedTimer> // 记录时间 | |
#include <QtDebug> | |
#include <QThread> | |
Generate::Generate(QObject *parent) : QObject(parent),QRunnable() | |
{ | |
setAutoDelete(true); | |
} | |
void Generate::recNum(int num) | |
{ | |
m_num = num; | |
} | |
void Generate::run() | |
{ | |
qDebug()<< "生成随机数的线程地址" <<QThread::currentThread(); | |
// 存放随机数 vector 容器 | |
QVector<int> list; // 子线程生成数据,要通过传递给主线程 | |
QElapsedTimer time; | |
time.start();// 开始记录 | |
for (int i = 0;i < m_num;++i) | |
{ | |
// 从尾部插入 | |
list.push_back(qrand()%100000); | |
} | |
qint64 milsec = time.elapsed(); // 毫秒 | |
qDebug()<< "生成" <<m_num << "个随机总数用时"<<milsec<<"毫秒"; | |
// 发送给主线程 | |
emit sendArray(list); // 将数据发给主线程 | |
} | |
// 冒泡排序,补齐 parent | |
BubbleSort::BubbleSort(QObject *parent) : QObject(parent),QRunnable() | |
{ | |
setAutoDelete(true); | |
} | |
// 接受传递的 vector 变量 | |
void BubbleSort::recArray(QVector<int> list) | |
{ | |
m_list = list; | |
} | |
// 实现冒泡排序,实现相邻两个元素的交换 | |
void BubbleSort::run() | |
{ | |
qDebug()<< "冒泡排序的线程地址" <<QThread::currentThread(); | |
// 存放随机数 vector 容器 | |
QElapsedTimer time; | |
time.start(); | |
int temp; | |
for(int i = 0;i<m_list.size();++i) | |
{ | |
for(int j =0;j<m_list.size()-i-1;++j) // 从后数往前比较 | |
{ | |
if(m_list[j]>m_list[j+1]) | |
{ | |
temp = m_list[j]; | |
m_list[j] = m_list[j+1]; | |
m_list[j+1]=temp; | |
} | |
} | |
} | |
qint64 milsec = time.elapsed(); | |
qDebug()<< "冒泡排序用时" <<milsec<<"毫秒"; | |
// 发送给主线程 | |
emit finish(m_list); // 将数据发给主线程 | |
} | |
// 快速,补齐 parent | |
QuickSort::QuickSort(QObject *parent) : QObject(parent),QRunnable() | |
{ | |
setAutoDelete(true); // 自动释放空间 | |
} | |
// 接受传递的 vector 变量 | |
void QuickSort::recArray(QVector<int> list) | |
{ | |
m_list = list; | |
} | |
// 实现快速排序 | |
void QuickSort::run() | |
{ | |
qDebug()<< "快速排序的线程地址" <<QThread::currentThread(); | |
// 存放随机数 vector 容器 | |
QElapsedTimer time; | |
time.start(); | |
// 快速排序算法 | |
quickSort(m_list,0,m_list.size()-1); | |
qint64 milsec = time.elapsed(); | |
qDebug()<< "快速排序用时" <<milsec<<"毫秒"; | |
// 发送给主线程 | |
emit finish(m_list); // 将数据发给主线程 | |
} | |
// 快排算法 | |
void QuickSort::quickSort(QVector<int> &s, int l, int r) | |
{ | |
if(l < r) | |
{ | |
int i = l,j=r; | |
// 拿出第一个元素,保存到 x 中,第一个位置为空 | |
int x = s[l]; | |
while (i < j) | |
{ | |
// 从右向左找小于 x 的数 | |
while (i < j && s[j] >= x) | |
{ | |
// 左移,直到遇到小于等于 x 的数 | |
j--; | |
} | |
if (i < j) | |
{ | |
// 将右侧找到的小于 x 的元素放入左侧坑中,右侧出现一个坑 | |
// 左侧元素索引后移 | |
s[i++] = s[j]; | |
} | |
// 从左向右找大于等于 x 的数 | |
while (i < j && s[i] < x) | |
{ | |
// 右移,直到遇到大于 x 的数 | |
i++; | |
} | |
if (i < j) | |
{ | |
// 将左侧找到的元素放入右侧坑中,左侧出现一个坑 | |
// 右侧元素索引向前移动 | |
s[j--] = s[i]; | |
} | |
} | |
// 此时 i=j, 将保存在 x 中的数填入坑中 | |
s[i] = x; | |
quickSort(s, l, i - 1); // 递归调用 | |
quickSort(s, i + 1, r); | |
} | |
} |
# 主函数调用
#include "mainwindow.h" | |
#include "ui_mainwindow.h" | |
#include "mythread.h" | |
#include <QThreadPool> | |
MainWindow::MainWindow(QWidget *parent) : | |
QMainWindow(parent), | |
ui(new Ui::MainWindow) | |
{ | |
ui->setupUi(this); | |
// 当运行,用户点击按钮,就要调用子线程生成随机数,传递给主线程 | |
// 创建任务类对象 | |
Generate* gen = new Generate; | |
BubbleSort * bubble = new BubbleSort; | |
QuickSort * quick = new QuickSort; | |
// 信号和槽,主函数将 starting 的数,传递给子线程的 recNum 用户接受数量 | |
connect(this,&MainWindow::starting,gen,&Generate::recNum); | |
// 启动子线程,使用信号与槽,当用户点击 | |
connect(ui->start,&QPushButton::clicked,this,[=]() | |
{ | |
emit starting(10000); | |
// 给子线程发送信号 | |
QThreadPool::globalInstance()->start(gen); // 线程池中运行 | |
}); | |
// 当有了随机数之后,开始起痘冒泡和快速排序线程 | |
// 在排序之前,线程要先拿到所需要的数据 | |
connect(gen,&Generate::sendArray,bubble,&BubbleSort::recArray); | |
connect(gen,&Generate::sendArray,quick,&QuickSort::recArray); | |
// 添加 connect 用于接受子线程传过来的 list 容器随机数 | |
// 连接子线程,但子线程信号 sendArray 运行时,主线程接受 | |
connect(gen,&Generate::sendArray,this,[=](QVector <int> list) | |
{ | |
// | |
// 主线程开始接受来自子线程发送过来的 list,于此同时子线程开始运行 | |
QThreadPool::globalInstance()->start(bubble); // 线程池中运行 | |
QThreadPool::globalInstance()->start(quick); // 线程池中运行 | |
for(int i =0;i<list.size();i++) | |
{ | |
ui->randlist->addItem(QString::number(list.at(i))); | |
} | |
}); | |
// 排序运行之后,将排序好的数据放到主线程 | |
connect(bubble,&BubbleSort::finish,this,[=](QVector<int> list) | |
{ | |
for(int i =0;i<list.size();++i) | |
{ | |
ui->bubblelist->addItem(QString::number(list.at(i))); | |
} | |
}); | |
connect(quick,&QuickSort::finish,this,[=](QVector<int> list) | |
{ | |
for(int i =0;i<list.size();++i) | |
{ | |
ui->quicklist->addItem(QString::number(list.at(i))); | |
} | |
}); | |
} | |
MainWindow::~MainWindow() | |
{ | |
delete ui; | |
} |
# 4,线程
# 头文件
#ifndef MYTHREAD_H | |
#define MYTHREAD_H | |
#include <QThread> | |
#include <QVector> | |
// 创建的子线程,生成随机数 | |
class Generate : public QThread | |
{ | |
Q_OBJECT | |
public: | |
explicit Generate(QObject *parent = nullptr); | |
// 接受主线程传过来的参数,随机数 num | |
void recNum(int num); | |
protected: | |
// 子线程运行函数 | |
void run() override; | |
signals: | |
// 使用信号槽将数据传递给主线程,界面操作只能由主线程来进行 | |
void sendArray(QVector<int> num); | |
public slots: | |
private: | |
// 设置信号槽接受主线程传过来的数据 | |
int m_num; | |
}; | |
// 冒泡排序 | |
class BubbleSort : public QThread | |
{ | |
Q_OBJECT | |
public: | |
explicit BubbleSort(QObject *parent = nullptr); | |
// 接受主线程传过来的参数,数组 | |
void recArray(QVector<int> list); | |
protected: | |
// 子线程运行函数 | |
void run() override; | |
signals: | |
// 使用信号槽将数据传递给主线程,界面操作只能由主线程来进行 | |
// 发送的有序数组 | |
void finish(QVector<int> list); | |
public slots: | |
private: | |
// 设置信号槽接受主线程传过来的数据 | |
QVector<int> m_list; | |
}; | |
// 快速排序 | |
class QuickSort : public QThread | |
{ | |
Q_OBJECT | |
public: | |
explicit QuickSort(QObject *parent = nullptr); | |
// 接受主线程传过来的参数,随机数 num | |
void recArray(QVector<int> list); | |
protected: | |
// 子线程运行函数 | |
void run() override; | |
signals: | |
// 使用信号槽将数据传递给主线程,界面操作只能由主线程来进行 | |
void finish(QVector<int> list); | |
public slots: | |
private: | |
// 设置信号槽接受主线程传过来的数据 | |
QVector<int> m_list; | |
// 实现快速排序算法 | |
// 容器,起始位置,结束位置 | |
void quickSort(QVector<int> &list,int l,int r); | |
}; | |
#endif // MYTHREAD_H |
# 函数实现
#include "mythread.h" | |
#include <QElapsedTimer> // 记录时间 | |
#include <QtDebug> | |
Generate::Generate(QObject *parent) : QThread(parent) | |
{ | |
} | |
void Generate::recNum(int num) | |
{ | |
m_num = num; | |
} | |
void Generate::run() | |
{ | |
qDebug()<< "生成随机数的线程地址" <<QThread::currentThread(); | |
// 存放随机数 vector 容器 | |
QVector<int> list; // 子线程生成数据,要通过传递给主线程 | |
QElapsedTimer time; | |
time.start();// 开始记录 | |
for (int i = 0;i < m_num;++i) | |
{ | |
// 从尾部插入 | |
list.push_back(qrand()%100000); | |
} | |
qint64 milsec = time.elapsed(); // 毫秒 | |
qDebug()<< "生成" <<m_num << "个随机总数用时"<<milsec<<"毫秒"; | |
// 发送给主线程 | |
emit sendArray(list); // 将数据发给主线程 | |
} | |
// 冒泡排序,补齐 parent | |
BubbleSort::BubbleSort(QObject *parent) : QThread(parent) | |
{ | |
} | |
// 接受传递的 vector 变量 | |
void BubbleSort::recArray(QVector<int> list) | |
{ | |
m_list = list; | |
} | |
// 实现冒泡排序,实现相邻两个元素的交换 | |
void BubbleSort::run() | |
{ | |
qDebug()<< "冒泡排序的线程地址" <<QThread::currentThread(); | |
// 存放随机数 vector 容器 | |
QElapsedTimer time; | |
time.start(); | |
int temp; | |
for(int i = 0;i<m_list.size();++i) | |
{ | |
for(int j =0;j<m_list.size()-i-1;++j) // 从后数往前比较 | |
{ | |
if(m_list[j]>m_list[j+1]) | |
{ | |
temp = m_list[j]; | |
m_list[j] = m_list[j+1]; | |
m_list[j+1]=temp; | |
} | |
} | |
} | |
qint64 milsec = time.elapsed(); | |
qDebug()<< "冒泡排序用时" <<milsec<<"毫秒"; | |
// 发送给主线程 | |
emit finish(m_list); // 将数据发给主线程 | |
} | |
// 快速,补齐 parent | |
QuickSort::QuickSort(QObject *parent) : QThread(parent) | |
{ | |
} | |
// 接受传递的 vector 变量 | |
void QuickSort::recArray(QVector<int> list) | |
{ | |
m_list = list; | |
} | |
// 实现快速排序 | |
void QuickSort::run() | |
{ | |
qDebug()<< "快速排序的线程地址" <<QThread::currentThread(); | |
// 存放随机数 vector 容器 | |
QElapsedTimer time; | |
time.start(); | |
// 快速排序算法 | |
quickSort(m_list,0,m_list.size()-1); | |
qint64 milsec = time.elapsed(); | |
qDebug()<< "快速排序用时" <<milsec<<"毫秒"; | |
// 发送给主线程 | |
emit finish(m_list); // 将数据发给主线程 | |
} | |
// 快排算法 | |
void QuickSort::quickSort(QVector<int> &s, int l, int r) | |
{ | |
if(l < r) | |
{ | |
int i = l,j=r; | |
// 拿出第一个元素,保存到 x 中,第一个位置为空 | |
int x = s[l]; | |
while (i < j) | |
{ | |
// 从右向左找小于 x 的数 | |
while (i < j && s[j] >= x) | |
{ | |
// 左移,直到遇到小于等于 x 的数 | |
j--; | |
} | |
if (i < j) | |
{ | |
// 将右侧找到的小于 x 的元素放入左侧坑中,右侧出现一个坑 | |
// 左侧元素索引后移 | |
s[i++] = s[j]; | |
} | |
// 从左向右找大于等于 x 的数 | |
while (i < j && s[i] < x) | |
{ | |
// 右移,直到遇到大于 x 的数 | |
i++; | |
} | |
if (i < j) | |
{ | |
// 将左侧找到的元素放入右侧坑中,左侧出现一个坑 | |
// 右侧元素索引向前移动 | |
s[j--] = s[i]; | |
} | |
} | |
// 此时 i=j, 将保存在 x 中的数填入坑中 | |
s[i] = x; | |
quickSort(s, l, i - 1); // 递归调用 | |
quickSort(s, i + 1, r); | |
} | |
} |
# 函数调用
#include "mainwindow.h" | |
#include "ui_mainwindow.h" | |
#include "mythread.h" | |
MainWindow::MainWindow(QWidget *parent) : | |
QMainWindow(parent), | |
ui(new Ui::MainWindow) | |
{ | |
ui->setupUi(this); | |
// 当运行,用户点击按钮,就要调用子线程生成随机数,传递给主线程 | |
// 创建子线程对象, | |
Generate* gen = new Generate; | |
BubbleSort * bubble = new BubbleSort; | |
QuickSort * quick = new QuickSort; | |
// 信号和槽,主函数将 starting 的数,传递给子线程的 recNum 用户接受数量 | |
connect(this,&MainWindow::starting,gen,&Generate::recNum); | |
// 启动子线程,使用信号与槽,当用户点击 | |
connect(ui->start,&QPushButton::clicked,this,[=]() | |
{ | |
emit starting(10000); | |
// 给子线程发送信号 | |
gen->start(); // 调用子线程运行方法 | |
}); | |
// 当有了随机数之后,开始起痘冒泡和快速排序线程 | |
// 在排序之前,线程要先拿到所需要的数据 | |
connect(gen,&Generate::sendArray,bubble,&BubbleSort::recArray); | |
connect(gen,&Generate::sendArray,quick,&QuickSort::recArray); | |
// 添加 connect 用于接受子线程传过来的 list 容器随机数 | |
// 连接子线程,但子线程信号 sendArray 运行时,主线程接受 | |
connect(gen,&Generate::sendArray,this,[=](QVector <int> list) | |
{ | |
// | |
// 主线程开始接受来自子线程发送过来的 list,于此同时子线程开始运行 | |
bubble->start(); | |
quick->start(); | |
for(int i =0;i<list.size();i++) | |
{ | |
ui->randlist->addItem(QString::number(list.at(i))); | |
} | |
}); | |
// 排序运行之后,将排序好的数据放到主线程 | |
connect(bubble,&BubbleSort::finish,this,[=](QVector<int> list) | |
{ | |
for(int i =0;i<list.size();++i) | |
{ | |
ui->bubblelist->addItem(QString::number(list.at(i))); | |
} | |
}); | |
connect(quick,&QuickSort::finish,this,[=](QVector<int> list) | |
{ | |
for(int i =0;i<list.size();++i) | |
{ | |
ui->quicklist->addItem(QString::number(list.at(i))); | |
} | |
}); | |
connect(this,&MainWindow::destroyed,this,[=]() | |
{ | |
gen->quit(); | |
gen->wait(); | |
gen->deleteLater(); // 释放空间 | |
bubble->quit(); | |
bubble->wait(); | |
bubble->deleteLater(); // 释放空间 | |
quick->quit(); | |
quick->wait(); | |
quick->deleteLater(); // 释放空间 | |
}); | |
} | |
MainWindow::~MainWindow() | |
{ | |
delete ui; | |
} |