• Qt创建线程(使用moveToThread方法创建子线程)


    1.moveToThread方法注意点:

    (1)要使用moveToThread方法必须继承与QObject类

    (2)创建任务对象时不能指定父对象

             例子:

                    MyWork* work = new MyWork(this); // error

                    MyWork* work = new MyWork; // ok

    (3)任务类里面的任务函数可以有多个

    (4)这种创建线程的方式很灵活,如果子线程不够用,可以把多个任务函数移动到其中的一个线程中,(一个子线程中可以移动多个任务函数,关联的多个任务函数是按照线性的顺序执行的)还可以先在线程1中执行任务函数a,然后在线程2中执行任务函数a(也就是一个任务函数可以在多个不同的线程中执行)

    (5)使用moveToThread方法时会出现两种情况,单线程情况和多线程情况:   

            单线程情况下,信号和槽函数属于同一个线程,可以不用指定connect的第五个参数;

            多线程情况下,信号和槽函数可以不在同一个线程下执行,需要指定connect的第五个参数来选择连接方式,例如:connect(sender, signal, receiver, slot,Qt::DirectConnection)//采用直接关联,当前槽函数在信号发送者的线程中执行

    注意:QThread和moveToThread两种方法都可以使用信号和槽

    2.moveToThread方法代码例子

    使用moveToThread方法实现点击开始按钮生成10000个随机数,然后分别使用冒泡排序和快速排序排序这10000个随机数,最后在窗口显示排序后的数字:

    mainwindow.h文件:

    1. //mainwindow.h
    2. #ifndef MAINWINDOW_H
    3. #define MAINWINDOW_H
    4. #include
    5. QT_BEGIN_NAMESPACE
    6. namespace Ui { class MainWindow; }
    7. QT_END_NAMESPACE
    8. class MainWindow : public QMainWindow
    9. {
    10. Q_OBJECT
    11. public:
    12. MainWindow(QWidget *parent = nullptr);
    13. ~MainWindow();
    14. signals:
    15. void starting(int num);
    16. private:
    17. Ui::MainWindow *ui;
    18. };
    19. #endif // MAINWINDOW_H

    mythread.h文件:

    1. //mythread.h
    2. #ifndef MYTHREAD_H
    3. #define MYTHREAD_H
    4. #include
    5. #include
    6. //生成随机数 第二种写法继承于QObject的MoveToThread方法实现多线程
    7. class MyThread : public QObject
    8. {
    9. Q_OBJECT
    10. public:
    11. explicit MyThread(QObject *parent = nullptr);
    12. void working(int num);
    13. signals:
    14. void sendArray(QVector<int> list);
    15. };
    16. class BubbleSort : public QObject
    17. {
    18. Q_OBJECT
    19. public:
    20. explicit BubbleSort(QObject *parent = nullptr);
    21. void working(QVector<int> list);
    22. signals:
    23. void finish(QVector<int> num);
    24. };
    25. class QuickSort : public QObject
    26. {
    27. Q_OBJECT
    28. public:
    29. explicit QuickSort(QObject *parent = nullptr);
    30. void working(QVector<int> list);
    31. private:
    32. void quickSort(QVector<int> &list, int l, int r);
    33. signals:
    34. void finish(QVector<int> num);
    35. };
    36. #endif // MYTHREAD_H

    main.cpp文件:

    1. //main.cpp
    2. #include "mainwindow.h"
    3. #include
    4. int main(int argc, char *argv[])
    5. {
    6. QApplication a(argc, argv);
    7. qRegisterMetaTypeint>>("QVector");
    8. MainWindow w;
    9. w.show();
    10. return a.exec();
    11. }

     mythread.cpp文件:

    1. //mthread.cpp
    2. #include "mythread.h"
    3. #include
    4. #include //计算某个流程执行所使用的时间
    5. #include
    6. #include
    7. MyThread::MyThread(QObject *parent)
    8. : QObject(parent)
    9. {
    10. }
    11. void MyThread::working(int num)
    12. {
    13. qDebug() << "生成随机数的线程地址" << QThread::currentThread(); //获取一个指针,这个指针指向当前线程对象的地址
    14. QVector<int> list;
    15. QElapsedTimer time;
    16. time.start();
    17. for(int i = 0; i < num; i++){
    18. list.push_back(qrand() % 100000);
    19. }
    20. int milsec = time.elapsed();
    21. qDebug() << "生成" << num << "个随机数总共用时:" << milsec << "毫秒";
    22. emit sendArray(list);
    23. }
    24. BubbleSort::BubbleSort(QObject *parent)
    25. :QObject(parent)
    26. {
    27. }
    28. void BubbleSort::working(QVector<int> list)
    29. {
    30. qDebug() << "冒泡排序的线程地址" << QThread::currentThread(); //获取一个指针,这个指针指向当前线程对象的地址
    31. QElapsedTimer time;
    32. time.start();
    33. for(int i = 0; i < list.size() - 1 ;i++){
    34. for(int j = 0;j < list.size() - i - 1; j++){
    35. if(list[j] > list[j + 1]){
    36. int temp = list[j];
    37. list[j] = list[j + 1];
    38. list[j + 1] = temp;
    39. }
    40. }
    41. }
    42. int milsec = time.elapsed();
    43. qDebug() << "冒泡排序用时" << milsec << "毫秒";
    44. emit finish(list);
    45. }
    46. QuickSort::QuickSort(QObject *parent)
    47. :QObject(parent)
    48. {
    49. }
    50. void QuickSort::quickSort(QVector<int> &s, int l, int r)
    51. {
    52. if(l < r){
    53. int i = l, j = r;
    54. int x = s[l];
    55. while(i < j){
    56. while(i < j &&s[j] >=x){
    57. j--;
    58. }
    59. if(i < j){
    60. s[i++] = s[j];
    61. }
    62. while(i < j && s[i] < x){
    63. i++;
    64. }
    65. if(i < j){
    66. s[j--] = s[i];
    67. }
    68. }
    69. s[i] = x;
    70. quickSort(s, l, i - 1);
    71. quickSort(s, i + 1, r);
    72. }
    73. }
    74. void QuickSort::working(QVector<int> list)
    75. {
    76. qDebug() << "快速排序的线程地址" << QThread::currentThread(); //获取一个指针,这个指针指向当前线程对象的地址
    77. QElapsedTimer time;
    78. time.start();
    79. quickSort(list, 0,list.size()-1);
    80. int milsec = time.elapsed();
    81. qDebug() << "快速排序用时" << milsec << "毫秒";
    82. emit finish(list);
    83. }

    mainwindow.cpp文件:

    1. //mainwindow.cpp
    2. #include "mainwindow.h"
    3. #include "ui_mainwindow.h"
    4. #include "mythread.h"
    5. #include
    6. MainWindow::MainWindow(QWidget *parent)
    7. : QMainWindow(parent)
    8. , ui(new Ui::MainWindow)
    9. {
    10. ui->setupUi(this);
    11. //1.创建子线程的对象
    12. QThread *t1 = new QThread;
    13. //QThread *t1 = new QThread(this); //error 使用moveTOThread方法创建子线程对象的时候不能指定父对象
    14. QThread *t2 = new QThread;
    15. QThread *t3 = new QThread; //创建三个子线程,现在系统中一共有四个线程(三个子线程和一个主线程)
    16. //2.创建任务类的对象
    17. MyThread *gen = new MyThread;
    18. BubbleSort *bubble = new BubbleSort;
    19. QuickSort *quick = new QuickSort;
    20. //3.将任务对象移动到某个子线程中
    21. gen->moveToThread(t1);
    22. bubble->moveToThread(t2);
    23. quick->moveToThread(t3);
    24. connect(this, &MainWindow::starting, gen, &MyThread::working);
    25. //2.启动子线程
    26. connect(ui->start, &QPushButton::clicked, this, [=]{
    27. emit starting(10000); //在启动子线程时,将要生成的随机数的个数发送出去
    28. t1->start();
    29. });
    30. //接收子线程发送的数据
    31. connect(gen, &MyThread::sendArray, bubble, &BubbleSort::working); //先关联再启动线程
    32. connect(gen, &MyThread::sendArray, quick, &QuickSort::working); //这里任务函数是在子线程中执行的
    33. /* connect(gen, &MyThread::sendArray, this,[](QVector list){//如果信号和槽函数不在同一个线程的情况
    34. bubble->working(list);
    35. quick->working(list);
    36. }); *///注意:此时这个匿名函数是在当前的主线程中执行的,但是我们是想让他在子线程中执行,这样就错误了,不满足我们的需求了
    37. connect(gen, &MyThread::sendArray, this, [=](QVector<int> list){ //connect里面不支持传递QVector类型//需要使用qRegisterMetaType()进行注册
    38. t2->start();
    39. t3->start();
    40. for(int i = 0; i < list.size(); i++){
    41. ui->randList->addItem(QString::number(list.at(i)));
    42. }
    43. });
    44. connect(bubble, &BubbleSort::finish, this, [=](QVector<int> list){ //connect里面不支持传递QVector类型//需要使用qRegisterMetaType()进行注册
    45. for(int i = 0; i < list.size(); i++){
    46. ui->bubbleList->addItem(QString::number(list.at(i)));
    47. }
    48. });
    49. connect(quick, &QuickSort::finish, this, [=](QVector<int> list){ //connect里面不支持传递QVector类型//需要使用qRegisterMetaType()进行注册
    50. for(int i = 0; i < list.size(); i++){
    51. ui->quickList->addItem(QString::number(list.at(i)));
    52. }
    53. });
    54. //2.当前窗口析构的时候,回收线程的资源
    55. //窗口关闭时,会发送一个destroyed()信号,就可以根据这个信号来销毁线程的资源
    56. connect(this, &MainWindow::destroyed, this,[=]{
    57. t1->quit();
    58. t1->wait();
    59. t1->deleteLater(); //delete t1 销毁线程t1的资源
    60. t2->quit();
    61. t2->wait();
    62. t2->deleteLater(); //delete t2 销毁线程t2的资源
    63. t3->quit();
    64. t3->wait();
    65. t3->deleteLater(); //delete t3 销毁线程t3的资源
    66. gen->deleteLater(); //释放任务对象gen
    67. bubble->deleteLater(); //释放任务对象bubble
    68. quick->deleteLater(); //释放任务对象quick
    69. });
    70. }
    71. MainWindow::~MainWindow()
    72. {
    73. delete ui;
    74. }

    运行结果:

  • 相关阅读:
    bugku-杂项-社工进阶收集
    【Unity3D日常开发】Unity3D中打包WEBGL后读取本地文件数据
    【ESP-S3-BOX-Lite花屏问题】:Github下载源码(出厂源码factory_demo)编译调试到ESP-S3-BOX-Lite中出现花屏现象
    【附源码】计算机毕业设计java缘来有交友平台系统设计与实现
    分布式网络通信框架(一)——集群和分布式
    常用git命令
    Leetcode 高频算法题
    字符串相乘
    [数据分析与可视化] Python绘制数据地图5-MovingPandas绘图实例
    K8S(4)DaemonSet
  • 原文地址:https://blog.csdn.net/weixin_44954230/article/details/133180808