qt线程介绍

目录

介绍

 线程类 QThread

 方式1

方式2

案例

线程资源释放


介绍

qt为多线程提供了完美的支持,实现多线程一般是从从QTHread中继承定义自己的线程类,QT也提供了QMutexLocker,QwaitCondition等类实现线程同步,与Linux系统或C++中的线程库类似。这里简单介绍下多线程的创建。

  • 默认的线程在Qt中称之为窗口线程,也叫主线程,负责窗口事件处理或者窗口控件数据的更新
  • 子线程负责后台的业务逻辑处理,子线程中不能对窗口对象做任何操作,这些事情需要交给窗口线程处理
  • 主线程和子线程之间如果要进行数据的传递,需要使用Qt中的信号槽机制

 线程类 QThread

常用API:

qt线程介绍_第1张图片

[virtual protected] void QThread::run();

run()是一个虚函数,如果想让创建的子线程执行某个任务,需要写一个子类让其继承QThread,并且在子类中重写父类的run()方法,函数体就是对应的任务处理流程,当前线程对象调用槽函数start()启动子线程,当子线程被启动,这个run()函数也就在线程内部被调用了。

信号与槽函数:

// 线程中执行的任务完成了, 发出该信号
[signal] void QThread::finished();
// 开始工作之前发出这个信号, 一般不使用
[signal] void QThread::started();

[slot] void QThread::quit();


// 启动子线程
[slot] void QThread::start(Priority priority = InheritPriority);
// 线程退出, 可能是会马上终止线程, 一般情况下不使用这个函数
[slot] void QThread::terminate();

 方式1

创建一个线程类的子类,让其继承QT中的线程类 QThread,重写父类的 run() 方法,启动子线程, 调用 start() 方法。

举例:

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include 
#include

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);
protected:
    void run();
signals:
     void curNumber(int num);
};

#endif // MYTHREAD_H
#include "mythread.h"
#include
MyThread::MyThread(QObject *parent)
{
}

void MyThread::run()
{
    qDebug() << "当前线程对象的地址: " << QThread::currentThread();

        int num = 0;
    while(1)
    {
        emit curNumber(num++);//子线程每秒发出一次信号
        if(num == 10000000)
        {
            break;
        }
        QThread::usleep(1);
    }
    qDebug() << "run() 执行完毕, 子线程退出...";

}
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    qDebug() << "主线程对象地址:  " << QThread::currentThread();
    MyThread* m=new MyThread;

    connect(m, &MyThread::curNumber, this, [=](int num)//子线程每秒发出一次信号
            {
                ui->label->setNum(num);
            });

    connect(ui->pushButton, &QPushButton::clicked, this, [=]()
            {
                // 启动子线程
              m ->start();
            });
}

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

方式2

  1. 创建一个新的类A,让这个类从QObject派生,这个类中添加一个公共的成员函数来处理对应的任务
  2. 在主线程中创建一个QThread对象
  3. 在主线程中创建工作的类对象A(不能指定父对象)
  4. 将对象A移动到创建的子线程对象中, 需要调用QObject类提供的moveToThread()方法
  5. 启动子线程,调用 start(), 这时候线程启动了, 但是移动到线程中的对象并没有工作
  6. 调用MyWork类对象的工作函数,让这个函数开始执行。

例如:

#ifndef WORK_H
#define WORK_H
#include 

class Work : public QObject
{
    Q_OBJECT
public:
    explicit Work(QObject *parent = nullptr);
    void Working();
signals:
     void curNumber(int num);

};
#endif // WORK_H
#include "work.h"
#include
#include
Work::Work(QObject *parent)
    : QObject{parent}
{
}

void Work::Working()
{
    qDebug() << "当前线程对象的地址: " << QThread::currentThread();

    int num = 0;
    while(1)
    {
        emit curNumber(num++);//子线程每秒发出一次信号
        if(num == 10000000)
        {
            break;
        }
        QThread::usleep(1);
    }
    qDebug() << "run() 执行完毕, 子线程退出...";
}
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    qDebug() << "主线程对象地址:  " << QThread::currentThread();

    QThread* sub = new QThread;//创建线程对象
    Work* w=new Work;          //创建工作对象,该对象包含业务处理方法,不要指定给创建的对象指定父对象
    w->moveToThread(sub);    //将工作对象移动到子线程中

    sub->start();
    connect(ui->startBtn, &QPushButton::clicked, w,&Work::Working);
    // 显示数据
    connect(w, &Work::curNumber, this, [=](int num)
            {
                ui->label->setNum(num);
            });
}



案例

在一个子线程程中随机生成1000个数,将这些数据交给另一个子线程去排序,后面将排序的结果返回给主线程,主线程再将数据输出到窗口中。

这里采用方案1进行演示:

生成随机数线程:

class Genera : public QThread //该类来生成随机数
{
    Q_OBJECT
public:
    explicit Genera(QObject *parent = nullptr);
    void getnum(int k);
protected:
    void run();//重写run方法,生成随机数
private:
    int num_;  //获取主线程传来的数据,这里为生成随机数的个数

signals:
    void sendnum(QVector v);//当随机数生成完后,发射该信号,将数据传给主线程和排序线程
};


Genera::Genera(QObject *parent)
    : QThread{parent}
{
}
void Genera::getnum(int k)
{
    num_=k;
}
void Genera::run()
{
    qDebug()<<"当前线程是"<<" "< v;
    QElapsedTimer q;
    q.start();
    for(int i=0;i

排序线程:

class BubbleSort : public QThread //该类来生成随机数
{
    Q_OBJECT
public:
    explicit BubbleSort(QObject *parent = nullptr);
    void getnum(QVector);//获取生成随机数线程传来的数据
protected:
    void run();//进行排序
private:
    QVector v;

signals:
    void Finish(QVector v);//排序完成后发射该信号,将排序结果给主线程
};

BubbleSort::BubbleSort(QObject *parent)
    : QThread{parent}
{ 
}
void BubbleSort::getnum(QVector list)
{
    v=list;
}
void BubbleSort::run()
{
     qDebug()<<"当前线程是"<<" "<v[j+1])
            {
                int tmp=v[j+1];
                v[j+1]=v[j];
                v[j]=tmp;
            }
        }
    }
    int m=q.elapsed();
    qDebug()<<"排序的时间是"<<" "<

主线程:

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
signals:
    void starting(int num);//生成随机数的个数

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //创建子线程
    Genera * g=new Genera;//生成随机数
    BubbleSort* b=new BubbleSort;//排序
    connect(this,&MainWindow::starting,g,&Genera::getnum);

    //启动子线程
    connect(ui->pushButton,&QPushButton::clicked,this,[=](){
        emit starting(1000);//发射该信号,将生成随机数的个数传给子线程
        g->start();
    });


    connect(g,&Genera::sendnum,b,&BubbleSort::getnum);//排序线程接受生成随机数线程传来的数据

    //接受子线程传来的排序数
    connect(g,&Genera::sendnum,this,[=](QVector v){
        //说明随机生成数已生成好
        b->start();
        for(int i=0;ilistWidget->addItem(QString::number(v.at(i)));
        }
    });

    connect(b,&BubbleSort::Finish,this,[=](QVector v){

        for(int i=0;ilistWidget_2->addItem(QString::number(v.at(i)));
        }
    });
}

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

 结果:

qt线程介绍_第2张图片

线程资源释放

1.创建线程时,给它指明父对象,让其添加到对象树列表中。

2.手动释放,调用quit,wait,delete:例如,在上面的代码中,new出来的时局部变量:

 connect(this,&MainWindow::destroyed,this,[=](){
        g->quit();
        g->wait();
        g->deleteLater();//类似与c++中delete
    });

你可能感兴趣的:(qt,qt,开发语言)