Qt中线程的简单使用

对于线程过去写的比较少,现在也几乎是小白的水平。先创建Qt empty project,即Qt空项目,打开QtCreate->文件->新建文件或项目->其它项目->empty qmke project,接着按提示创建Qt空项目,创建之后,在项目上右键添加新文件,选择源文件,创建main.cpp文件,添加如下代码:
main.cpp

#include <QtCore>

int main(int argc,char* argv[])
{
    QCoreApplication app(argc,argv);
    return app.exec();
}

再添加新文件,选择类,基类为QThread,类名为myThread,最后添加代码后文件内容为:
myThread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>

class myThread : public QThread
{
    Q_OBJECT
public:
    explicit myThread(QObject *parent = nullptr);
protected:
    void run();
private:
//    volatile bool stopped;
};

#endif // MYTHREAD_H

myThread.cpp

#include "mythread.h"
#include "Counter.h"
#include <QDebug>

myThread::myThread(QObject *parent):
    QThread(parent)
{
//    stopped = false;
}

void myThread::run()
{
    Counter counter;
    quint8 i = 4;
    while(i--)
    {
        counter.increment();
//        int n = counter.GetValue();
//       qDebug()<<QString("n:").arg(counter.GetValue());
        qDebug()<<"n:"<<counter.GetValue();
    }
}

再添加另一个线程类,同样在项目上右键添加新文件,选择类,类名mythreadread,基类为QThread,创建好这个类之后,添加完代码之后,文件内容如下:
mythreadread.h

#ifndef MYTHREADREAD_H
#define MYTHREADREAD_H

#include <QThread>

class mythreadread : public QThread
{
    Q_OBJECT
public:
    explicit mythreadread(QObject *parent = nullptr);
protected:
    void run();
};

#endif // MYTHREADREAD_H

mythreadread.cpp

#include "mythreadread.h"
#include "Counter.h"
#include <QDebug>

mythreadread::mythreadread(QObject *parent):
    QThread(parent)
{

}

void mythreadread::run()
{
    Counter counter;
    quint8 i = 4;
    while(i--)
    {
        counter.decrement();
        qDebug()<<"n="<<counter.GetValue();
    }
}

以上两个线程类创建完成之后,在项目上右键添加新文件Counter.h,即添加头文件,添加之后,修改其代码如下:
Counter.h

#ifndef COUNTER_H
#define COUNTER_H

class Counter
{
public:
    Counter():n(0){}
    void increment(){n++;}
    void decrement(){n--;}
    int GetValue()const{return n;}//该函数不能修改类成员变量的值
private:
    int n;
};
#endif // COUNTER_H

现在在main函数中修改代码如下:
main.cpp

#include <QtCore>
#include "mythread.h"
#include "mythreadread.h"

myThread thread1;
mythreadread thread2;

int main(int argc,char* argv[])
{
    QCoreApplication app(argc,argv);

    //针对各自线程中的特定对象的成员操作,互不影响
    thread1.start();
    thread1.wait();

    thread2.start();
    thread2.wait();
    return app.exec();
}

运行程序,结果如下:
n: 1
n: 2
n: 3
n: 4
n= -1
n= -2
n= -3
n= -4
结论:第一个线程启动后,在其线程函数中创建了Counter的类对象,并循环调用四次Counter类的加计数函数,然后输出每一次加计数后的值,最后调用wait()函数等待线程的结束,第一个线程结束之后,启动第二个线程,在该线程中对Counter类的成员变量减计数,并输出每一次减计数后的值,最后等带线程二结束之后,主程序关闭。其中有三个点需要注意:

  1. 在Counter类的定义中,将函数的声明与定义放在了同一个文件Counter.h中。需要注意的是,在同一个文件中定义并声明一个类时,函数的定义不能在该类外,否则会出现错误提示,重定义该文件。像下面所写一样:
#ifndef COUNTER_H
#define COUNTER_H

class Counter
{
public:
    Counter():n(0){}
   
    int GetValue();
private:
    int n;
};
void Counter::GetValue()
{
    return n;
}
#endif // COUNTER_H

这样在类中定义成员函数,会导致编译错误,只能在类中进行定义。

#ifndef COUNTER_H
#define COUNTER_H

class Counter
{
public:
    Counter():n(0){}
    int GetValue(){return n;}
private:
    int n;
};

#endif // COUNTER_H
  1. 引入可重入的概念,一个类可以被多个线程使用,但每一次只能是调用该类自己的成员函数或成员变量。上面两个线程,在run()函数中分别对Counter类的成员函数进行操作,针对的是每一个Counter类自己的成员函数的操作,所以两个线程之间没有涉及到数据共享,线程同步等问题,可以线程实际是独立的。
  2. 如果将main.cpp中主函数中的两个线程的启动顺序变为如下:
   	thread1.start();
    thread2.start();
    
    thread1.wait();  
    thread2.wait();

那么程序的运行结果是怎么样呢?其运行结果如下:
n: 1
n= -1
n: 2
n= -2
n: 3
n= -3
n: 4
n= -4
可以看出,两个线程几乎是同时运行的,他们之间并行运行各自的run()函数,在对Counter类操作时,n的初始值都是从0开始,互不影响。
附加总结:
创建线程的方法之一是创建一个继承自QThread的类,引入#include头文件,在类的声明的开头加入Q_OBJECT宏,在类中重写run()函数,在类定义中对run()函数进行定义,即线程需要做的事情在run()函数中编写,线程类便创建完成了。线程调用时引入线程所在类的头文件,在需要线程的地方,定义线程对象,并调用start()函数启动线程,线程结束的地方可以调用stop()函数停止线程,但在之前最好加上wait()函数等待线程的结束。

terminate的说明

terminate并不会立即终止线程,它取决于系统的调度,此外调用这个函数时最好在其后调用一下wait()函数等待线程结束,但是terminate()存在危险性,因为无法知道它在何时会关闭线程,而且关闭线程时不会做清理工作,尽量少用。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

肩上风骋

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

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

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

打赏作者

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

抵扣说明:

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

余额充值