Qt创建线程(线程池)

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

(1)线程池继承于QRunnable

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

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

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

2.使用线程池代码例子

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

mainwindow.h文件:

//mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
signals:
    void starting(int num);
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mythread.h文件:

//mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QRunnable>
//生成随机数
class MyThread : public QObject,public QRunnable //要使用Qt的信号槽继承就必须要继承QObject类(实现多继承)(注意QObject类要写在前面)
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);
    void recvNum(int num);
    void run() override;
signals:
    void sendArray(QVector<int> list);
private:
    int m_num;
};

class BubbleSort : public QObject,public QRunnable
{
    Q_OBJECT
public:
    explicit BubbleSort(QObject *parent = nullptr);
    void recvArray(QVector<int> list);
    void run() override;
signals:
    void finish(QVector<int> num);
private:
    QVector<int> m_list;
};

class QuickSort : public QObject,public QRunnable
{
    Q_OBJECT
public:
    explicit QuickSort(QObject *parent = nullptr);
    void recvArray(QVector<int> list);
private:
    void quickSort(QVector<int> &list, int l, int r);
    void run() override;
signals:
    void finish(QVector<int> num);
private:
    QVector<int> m_list;

};
#endif // MYTHREAD_H

main.cpp文件:

//main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    qRegisterMetaType<QVector<int>>("QVector<int>");
    MainWindow w;
    w.show();
    return a.exec();
}

mythread.cpp文件:


//mythread.cpp

#include "mythread.h"
#include <QVector>
#include <QElapsedTimer> //计算某个流程执行所使用的时间
#include <QDebug>
#include <QThread>

MyThread::MyThread(QObject *parent)
    : QObject(parent), QRunnable()
{
    setAutoDelete(true); //设置当前这个线程的对象放到线程池里后,在工作完毕后自动释放
}

void MyThread::recvNum(int num)
{
    m_num = num;
}

void MyThread::run()
{
    qDebug() << "生成随机数的线程地址" << QThread::currentThread(); //获取一个指针,这个指针指向当前线程对象的地址
    QVector<int> list;
    QElapsedTimer time;
    time.start();
    for(int i = 0; i < m_num; i++){
        list.push_back(qrand() % 100000);
    }
    int milsec = time.elapsed();
    qDebug() << "生成" << m_num << "个随机数总共用时:" << milsec << "毫秒";
    emit sendArray(list);
}

BubbleSort::BubbleSort(QObject *parent)
    : QObject(parent), QRunnable()
{
    setAutoDelete(true); //设置当前这个线程的对象放到线程池里后,在工作完毕后自动释放
}


void BubbleSort::recvArray(QVector<int> list)
{
    m_list = list;
}

void BubbleSort::run()
{
    qDebug() << "冒泡排序的线程地址" << QThread::currentThread(); //获取一个指针,这个指针指向当前线程对象的地址
    QElapsedTimer time;
    time.start();
    for(int i = 0; i < m_list.size() - 1 ;i++){
        for(int j = 0;j < m_list.size() - i - 1; j++){
            if(m_list[j] > m_list[j + 1]){
                int temp = m_list[j];
                m_list[j] = m_list[j + 1];
                m_list[j + 1] = temp;
            }
        }
    }
    int milsec = time.elapsed();
    qDebug() << "冒泡排序用时" << milsec << "毫秒";
    emit finish(m_list);
}

QuickSort::QuickSort(QObject *parent)
    : QObject(parent), QRunnable()
{
    setAutoDelete(true); //设置当前这个线程的对象放到线程池里后,在工作完毕后自动释放
}


void QuickSort::recvArray(QVector<int> list)
{
    m_list = list;
}

void QuickSort::quickSort(QVector<int> &s, int l, int r)
{
    if(l < r){
        int i = l, j = r;
        int x = s[l];
        while(i < j){
            while(i < j &&s[j] >=x){
                j--;
            }
            if(i < j){
                s[i++] = s[j];
            }
            while(i < j && s[i] < x){
                i++;
            }
            if(i < j){
                s[j--] = s[i];
            }
        }
        s[i] = x;
        quickSort(s, l, i - 1);
        quickSort(s, i + 1, r);
    }
}

void QuickSort::run()
{
    qDebug() << "快速排序的线程地址" << QThread::currentThread(); //获取一个指针,这个指针指向当前线程对象的地址
    QElapsedTimer time;
    time.start();
    quickSort(m_list, 0,m_list.size()-1);
    int milsec = time.elapsed();
    qDebug() << "快速排序用时" << milsec << "毫秒";
            emit finish(m_list);
}

mainwindow.cpp文件:

//mainwindow.cpp

#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);
    //1.创建任务类对象
    MyThread *gen = new MyThread;
    BubbleSort *bubble = new BubbleSort;
    QuickSort *quick = new QuickSort;
    connect(this, &MainWindow::starting, gen, &MyThread::recvNum);
    //2.启动子线程
    connect(ui->start, &QPushButton::clicked, this, [=]{
        emit starting(10000); //在启动子线程时,将要生成的随机数的个数发送出去
        QThreadPool::globalInstance()->start(gen); //将任务类对象(生成随机数)丢到线程池中


    });
    //接收子线程发送的数据
    connect(gen, &MyThread::sendArray, bubble, &BubbleSort::recvArray);
    connect(gen, &MyThread::sendArray, quick, &QuickSort::recvArray);
    connect(gen, &MyThread::sendArray, this, [=](QVector<int> list){ //connect里面不支持传递QVector类型//需要使用qRegisterMetaType()进行注册
       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){ //connect里面不支持传递QVector类型//需要使用qRegisterMetaType()进行注册
        for(int i = 0; i < list.size(); i++){
            ui->bubbleList->addItem(QString::number(list.at(i)));
        }
    });
    connect(quick, &QuickSort::finish, this, [=](QVector<int> list){ //connect里面不支持传递QVector类型//需要使用qRegisterMetaType()进行注册
        for(int i = 0; i < list.size(); i++){
            ui->quickList->addItem(QString::number(list.at(i)));
        }
    });
    
}


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

运行结果:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Qt线程池Qt提供的一种管理线程的机制,它可以帮助我们更有效地利用系统资源,并方便地进行多线程编程。 Qt线程池中的线程是共享的,这意味着多个任务可以在同一个线程中执行。线程池内部会维护一组可用的线程,当有任务需要执行时,会选择一个空闲的线程来执行任务。通过共享线程的方式,线程池可以减少线程创建和销毁的开销,提高线程的复用性。 在使用Qt线程池时,我们可以将一些待执行的任务(比如耗时的计算、网络请求等)封装成QRunnable对象,并将其提交给线程池线程池会自动将这些任务分配给空闲线程执行,而不需要我们手动创建和管理线程线程池的共享机制可以提高程序的性能和响应速度。通过共享线程线程池可以更好地管理线程的数量,避免过多的线程创建和销毁过程,从而减少了系统资源的消耗。而且,线程池可以实现任务的并行执行,提高任务处理的效率。 不过需要注意的是,在使用Qt线程池的过程中,我们需要在处理任务时保证线程安全。由于线程池中的线程是共享的,多个任务可能会同时在同一个线程中执行。因此,如果任务之间有共享的数据,必须使用互斥锁等机制来保护共享数据的访问,防止出现数据竞争和异常行为。 总而言之,Qt线程池提供了一种方便且高效的多线程编程机制,通过线程共享的方式减少了线程创建和销毁的开销,提高了程序的性能和响应速度。同时,我们需要注意线程安全性,在处理共享数据时使用适当的同步机制。 ### 回答2: 在Qt中,线程池是一种用于管理和调度线程的机制,它能够实现线程的复用,提高多线程编程的效率。线程池可以用于并行执行多个任务,每个任务由一个线程来处理。 Qt线程池使用QThreadPool类来实现,它提供了一组方法来管理线程池的大小、任务的提交和取消等操作。线程池中的线程是由Qt框架自动创建和管理的,可以通过设置线程池大小来控制线程的数量。线程池中的线程是共享的,即多个任务可以被同一个线程处理。 线程池的共享性能够节省资源,避免为每个任务都单独创建和销毁线程,从而减少了线程切换的开销。在每个任务执行完成后,线程会自动归还给线程池,以便被下一个任务使用。这样一来,线程池中的线程可以被多个任务共享,从而提高了系统的并发性能。 线程池的共享特性还可以通过Qt中的信号与槽机制实现线程间的通信。例如,一个任务在执行过程中需要与其他线程进行数据交换,可以通过发送信号和槽的方式实现线程间的消息传递。 总之,Qt线程池可以实现线程的复用和共享,提高多线程编程的效率和性能。它是一种非常实用的多线程技术,适用于需要并行执行多个任务的场景。 ### 回答3: Qt是一个跨平台的C++开发库,提供了线程池线程共享的功能。 线程池是一种线程管理机制,它维护一个线程的集合,以便在需要的时候可以复用这些线程,而不需要显式地创建和销毁线程Qt提供了QThreadPool类,它可以用于创建和管理线程池。通过使用线程池,可以更方便地处理并发任务,提高应用程序的性能和响应能力。 线程共享是指多个线程可以同时访问和修改共享的数据。在多线程编程中,线程之间共享的数据可能存在竞争条件和数据不一致的问题。为了避免这些问题,Qt提供了一些线程同步和互斥的机制。比如使用QMutex和QMutexLocker可以控制对临界区的访问,一次只允许一个线程进入;使用QReadWriteLock可以实现读写线程之间的互斥;使用QWaitCondition可以实现线程之间的条件等待和通知。 在Qt中,线程池线程共享是可以同时使用的。线程池可以创建多个线程,并管理它们的执行,而线程之间可以共享数据,并使用适当的线程同步机制来保证数据的一致性。通过合理地使用线程池线程共享,可以提高应用程序的并发性能,提升用户体验。同时,Qt提供了丰富的线程管理和同步机制,使得多线程编程更加简单和可靠。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lune_one

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值