QT 初识多线程

1.QThread线程基础

QThread是Qt线程中有一个公共的抽象类,所有的线程类都是从QThread抽象类中派生的,需要实现QThread中的虚函数run(),通过start()函数来调用run函数。

    void run()函数是线程体函数,用于定义线程的功能。

    void start()函数是启动函数,用于将线程入口地址设置为run函数。

    void terminate()函数用于强制结束线程,不保证数据完整性和资源释放。

    QCoreApplication::exec()总是在主线程(执行main()的线程)中被调用,不能从一个QThread中调用。在GUI程序中,主线程也称为GUI线程,是唯一允许执行GUI相关操作的线程。另外,必须在创建一个QThread前创建QApplication(or QCoreApplication)对象。

    当线程启动和结束时,QThread会发送信号started()finished(),可以使用isFinished()和isRunning()来查询线程的状态。

从Qt4.8起,可以释放运行刚刚结束的线程对象,通过连接finished()信号到QObject::deleteLater()槽。 
    使用wait()来阻塞调用的线程,直到其它线程执行完毕(或者直到指定的时间过去)。

    静态函数currentThreadId()currentThread()返回标识当前正在执行的线程。前者返回线程的ID,后者返回一个线程指针。

    要设置线程的名称,可以在启动线程之前调用setObjectName()。如果不调用setObjectName(),线程的名称将是线程对象的运行时类型(QThread子类的类名)。

应用程序的线程称为主线程,额外创建的线程为工作线程。一般在主线程里面创建工作线程,并调用 start() 开始执行工作线程的任务。start()会在内部调用run()函数,进入工作线程的循环,在 run() 函数里调用 exit() 或 quit() 可以结束线程的事件循环,或在主线程里调用 terminate() 强制结束线程。

                                                            QThread类的主要接口
类型 函数 功能
       公共函数 bool  isFinished () 线程是否结束
bool  isRunning () 线程是否正在运行
Priority  priority () 返回线程的优先级
void setPriority (Priority  priority) 设置线程的优先级
void exit(int returnCode=0) 退出事件的循环,退出码为returnCode ,0表示成功,否则表示有错误
bool wait(unsigned long time) 阻止线程执行,直到线程结束(从run函数返回),或等待时间超过time毫秒
公共槽函数 void  quit() 退出线程的事件循环,并返回代码0,等效于exit()
void  start(Priority  priority) 内部调用run()函数开始执行线程,操作系统根据priority参数进行调度终止线程的运行,但不是立即结束线程,而是等待操作系统结束线程。使用terminate()之后应使用wait()
void terminate()
 信号 void  finished() 在线程结束时发射此信号
void start() 在线程开始执行、run()函数被调用之前发射此信号
静态公共函数 int  idealThreadCount() 返回系统上能运行的线程的理性个数
void  msleep(unsigned long msecs)  强制当前线程休眠msecs毫秒
void sleep(unsigned long secs) 强制当前线程休眠secs秒
void  usleep(unsigned long usecs)  强制当前线程休眠uecs微秒
保护函数 virtual void run() start()调用run()函数开始线程任务的执行,所以在run()函数里实现线程的任务功能
int exec() 由run()函数调用,进入线程的时间循环,等待exit()退出

2.小案例

threaddlg.h
#ifndef THREADDLG_H
#define THREADDLG_H
#define  MAXSIZE 5
#include "workthread.h"
#include 
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class Threaddlg; }
QT_END_NAMESPACE

class Threaddlg : public QDialog
{
    Q_OBJECT

public:
    Threaddlg(QWidget *parent = nullptr);
    ~Threaddlg();

private:
    Ui::Threaddlg *ui;
    QPushButton  *startBtn;
    QPushButton  *stopBtn;
    QPushButton  *quitBtn;

    WorkThread *workThread[MAXSIZE];

public  slots:
    void  slotStart();
    void  slotStop();



};
#endif // THREADDLG_H

threaddlg.cpp

#include "threaddlg.h"
#include "ui_threaddlg.h"
#include
Threaddlg::Threaddlg(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::Threaddlg)
{
    ui->setupUi(this);
    setWindowTitle(QStringLiteral("线程"));

    startBtn=new QPushButton(QStringLiteral("线程"));
    stopBtn=new QPushButton(QStringLiteral("停止"));
    quitBtn=new QPushButton(QStringLiteral("退出"));
    QHBoxLayout *mainLayout=new QHBoxLayout(this);
    mainLayout->addWidget(startBtn);
    mainLayout->addWidget(stopBtn);
    mainLayout->addWidget(quitBtn);

    connect(startBtn,SIGNAL(clicked()),this,SLOT(slotStart()));
    connect(stopBtn,SIGNAL(clicked()),this,SLOT(slotStop()));
    connect(quitBtn,SIGNAL(clicked()),this,SLOT(close()));

}

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

void Threaddlg::slotStart()
{
    for(int i=0;istart();//调用QThread基类start函数,此函数将启动run,使线程开始真正运行
    }
    startBtn->setEnabled(false);
    stopBtn->setEnabled(true);
}

void Threaddlg::slotStop()
{
     for(int i=0;iterminate();//terminate函数不会立刻终止这个线程,该线程何时终止取决于操作系统的调度策略
          workThread[i]->wait();//使线程阻塞等待直到退出或超时
     }
     startBtn->setEnabled(true);
     stopBtn->setEnabled(false);
}

WorkThread.h
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include 
#include 
class WorkThread : public QThread
{
public:
    WorkThread();

protected:
    void  run();
};

#endif // WORKTHREAD_H

 WorkThread.cpp

 #include "workthread.h"

WorkThread::WorkThread()
{

}

void WorkThread::run()
{
    while(true)
    {
        for(int n=0;n<10;n++)
            qDebug()<

结果:

          1个线程                                                                                                           5个线程

 QT 初识多线程_第1张图片QT 初识多线程_第2张图片

 可以看出,一个线程输出是顺序打印的,5个线程也就是多线程的输出结果是乱码打印的

犯了一个很低级的错误

报错为:

原来是因为:    对了,就是clicked没有加括号

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