• Qt创建线程(线程池)


    1.使用线程池时的注意点

    (1)线程池继承于QRunnable

    (2)线程池可以创建线程统一的管理线程(统一创建、释放线程)

    (3)线程池不能直接使用信号和槽,可以使用多继承,继承QObject来使用信号和槽

    补充:还可以使用QtConcurrent::run()方法来创建线程,这个的实现是基于多线程

    2.使用线程池代码例子

    使用线程池方法实现点击开始按钮生成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. //生成随机数
    7. class MyThread : public QObject,public QRunnable //要使用Qt的信号槽继承就必须要继承QObject类(实现多继承)(注意QObject类要写在前面)
    8. {
    9. Q_OBJECT
    10. public:
    11. explicit MyThread(QObject *parent = nullptr);
    12. void recvNum(int num);
    13. void run() override;
    14. signals:
    15. void sendArray(QVector<int> list);
    16. private:
    17. int m_num;
    18. };
    19. class BubbleSort : public QObject,public QRunnable
    20. {
    21. Q_OBJECT
    22. public:
    23. explicit BubbleSort(QObject *parent = nullptr);
    24. void recvArray(QVector<int> list);
    25. void run() override;
    26. signals:
    27. void finish(QVector<int> num);
    28. private:
    29. QVector<int> m_list;
    30. };
    31. class QuickSort : public QObject,public QRunnable
    32. {
    33. Q_OBJECT
    34. public:
    35. explicit QuickSort(QObject *parent = nullptr);
    36. void recvArray(QVector<int> list);
    37. private:
    38. void quickSort(QVector<int> &list, int l, int r);
    39. void run() override;
    40. signals:
    41. void finish(QVector<int> num);
    42. private:
    43. QVector<int> m_list;
    44. };
    45. #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. //mythread.cpp
    2. #include "mythread.h"
    3. #include
    4. #include //计算某个流程执行所使用的时间
    5. #include
    6. #include
    7. MyThread::MyThread(QObject *parent)
    8. : QObject(parent), QRunnable()
    9. {
    10. setAutoDelete(true); //设置当前这个线程的对象放到线程池里后,在工作完毕后自动释放
    11. }
    12. void MyThread::recvNum(int num)
    13. {
    14. m_num = num;
    15. }
    16. void MyThread::run()
    17. {
    18. qDebug() << "生成随机数的线程地址" << QThread::currentThread(); //获取一个指针,这个指针指向当前线程对象的地址
    19. QVector<int> list;
    20. QElapsedTimer time;
    21. time.start();
    22. for(int i = 0; i < m_num; i++){
    23. list.push_back(qrand() % 100000);
    24. }
    25. int milsec = time.elapsed();
    26. qDebug() << "生成" << m_num << "个随机数总共用时:" << milsec << "毫秒";
    27. emit sendArray(list);
    28. }
    29. BubbleSort::BubbleSort(QObject *parent)
    30. : QObject(parent), QRunnable()
    31. {
    32. setAutoDelete(true); //设置当前这个线程的对象放到线程池里后,在工作完毕后自动释放
    33. }
    34. void BubbleSort::recvArray(QVector<int> list)
    35. {
    36. m_list = list;
    37. }
    38. void BubbleSort::run()
    39. {
    40. qDebug() << "冒泡排序的线程地址" << QThread::currentThread(); //获取一个指针,这个指针指向当前线程对象的地址
    41. QElapsedTimer time;
    42. time.start();
    43. for(int i = 0; i < m_list.size() - 1 ;i++){
    44. for(int j = 0;j < m_list.size() - i - 1; j++){
    45. if(m_list[j] > m_list[j + 1]){
    46. int temp = m_list[j];
    47. m_list[j] = m_list[j + 1];
    48. m_list[j + 1] = temp;
    49. }
    50. }
    51. }
    52. int milsec = time.elapsed();
    53. qDebug() << "冒泡排序用时" << milsec << "毫秒";
    54. emit finish(m_list);
    55. }
    56. QuickSort::QuickSort(QObject *parent)
    57. : QObject(parent), QRunnable()
    58. {
    59. setAutoDelete(true); //设置当前这个线程的对象放到线程池里后,在工作完毕后自动释放
    60. }
    61. void QuickSort::recvArray(QVector<int> list)
    62. {
    63. m_list = list;
    64. }
    65. void QuickSort::quickSort(QVector<int> &s, int l, int r)
    66. {
    67. if(l < r){
    68. int i = l, j = r;
    69. int x = s[l];
    70. while(i < j){
    71. while(i < j &&s[j] >=x){
    72. j--;
    73. }
    74. if(i < j){
    75. s[i++] = s[j];
    76. }
    77. while(i < j && s[i] < x){
    78. i++;
    79. }
    80. if(i < j){
    81. s[j--] = s[i];
    82. }
    83. }
    84. s[i] = x;
    85. quickSort(s, l, i - 1);
    86. quickSort(s, i + 1, r);
    87. }
    88. }
    89. void QuickSort::run()
    90. {
    91. qDebug() << "快速排序的线程地址" << QThread::currentThread(); //获取一个指针,这个指针指向当前线程对象的地址
    92. QElapsedTimer time;
    93. time.start();
    94. quickSort(m_list, 0,m_list.size()-1);
    95. int milsec = time.elapsed();
    96. qDebug() << "快速排序用时" << milsec << "毫秒";
    97. emit finish(m_list);
    98. }

    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. MyThread *gen = new MyThread;
    13. BubbleSort *bubble = new BubbleSort;
    14. QuickSort *quick = new QuickSort;
    15. connect(this, &MainWindow::starting, gen, &MyThread::recvNum);
    16. //2.启动子线程
    17. connect(ui->start, &QPushButton::clicked, this, [=]{
    18. emit starting(10000); //在启动子线程时,将要生成的随机数的个数发送出去
    19. QThreadPool::globalInstance()->start(gen); //将任务类对象(生成随机数)丢到线程池中
    20. });
    21. //接收子线程发送的数据
    22. connect(gen, &MyThread::sendArray, bubble, &BubbleSort::recvArray);
    23. connect(gen, &MyThread::sendArray, quick, &QuickSort::recvArray);
    24. connect(gen, &MyThread::sendArray, this, [=](QVector<int> list){ //connect里面不支持传递QVector类型//需要使用qRegisterMetaType()进行注册
    25. QThreadPool::globalInstance()->start(bubble); //将任务类对象(冒泡排序)丢到线程池中
    26. QThreadPool::globalInstance()->start(quick); //将任务类对象(快速排序)丢到线程池中
    27. for(int i = 0; i < list.size(); i++){
    28. ui->randList->addItem(QString::number(list.at(i)));
    29. }
    30. });
    31. connect(bubble, &BubbleSort::finish, this, [=](QVector<int> list){ //connect里面不支持传递QVector类型//需要使用qRegisterMetaType()进行注册
    32. for(int i = 0; i < list.size(); i++){
    33. ui->bubbleList->addItem(QString::number(list.at(i)));
    34. }
    35. });
    36. connect(quick, &QuickSort::finish, this, [=](QVector<int> list){ //connect里面不支持传递QVector类型//需要使用qRegisterMetaType()进行注册
    37. for(int i = 0; i < list.size(); i++){
    38. ui->quickList->addItem(QString::number(list.at(i)));
    39. }
    40. });
    41. }
    42. MainWindow::~MainWindow()
    43. {
    44. delete ui;
    45. }

    运行结果:

            通过运行结果可以发现:生成随机数的线程和冒泡排序的线程是使用线程池中的同一个线程,生成随机数的线程结束后就空闲了,然后又来了两个任务冒泡排序和快速排序,所以就又使用了这个空闲的任务来运行冒泡排序,然后快速排序用到了线程池里面的另一个线程。通过这点可以知道:通过线程池可以最大程度利用线程,减少资源的浪费。

  • 相关阅读:
    nacos适配达梦、瀚高、人大金仓数据库及部分源码探究
    分析高数值孔径物镜的聚焦特性
    关于openfeign的http和rpc
    Jupyter Notebook在指定位置打开
    媒体管理软件Jellyseerr
    从 Delta 2.0 开始聊聊我们需要怎样的数据湖
    FPGA - 7系列 FPGA SelectIO -05- 逻辑资源之OLOGIC
    小试牛刀-Telebot区块链游戏机器人
    KSF绩效管理
    GO语言篇之CGO
  • 原文地址:https://blog.csdn.net/weixin_44954230/article/details/133182034