使用qt实现多线程编程

目录

1、线程基础

1.1、GUI线程与工作线程

1.2、数据的同步访问

2、QT多线程简介

3、QThread线程类

4、创建并启动线程


        QThread类提供不依赖于平台的管理线程的方法。一个QThread类的对象管理一个线程,一 般从QThread继承一个自定义类,并重定义虚函数run(),在run()函数里实现线程需要完成的任务。

1、线程基础

1.1、GUI线程与工作线程

        每个程序启动后拥有的第一个线程称为主线程,即GUI线程。QT中所有的组件类和几个相关的类只能工作在GUI线程,不能工作在次线程,次线程即工作线程,主要负责处理GUI线程卸下的工作。

        所以,一些GUI显示的工作只能放在主线程,不能放在工作线程中。

1.2、数据的同步访问

        每个线程都有自己的栈,因此每个线程都有自己的调用历史和本地变量。线程共享相同的地址空间。

2、QT多线程简介

        QT通过三种形式提供了对线程的支持,分别是平台无关的线程类、线程安全的事件投递、跨线程的信号-槽连接。

QT中线程类包含如下:

        1)QThread 提供了跨平台的多线程解决方案;

        2)QThreadStorage 提供逐线程数据存储

        3)QMutex 提供相互排斥的锁,或互斥量;QMutexLocker 是一个辅助类,自动对 QMutex 加锁与解锁;

        4)QReadWriterLock 提供了一个可以同时读操作的锁;QReadLocker与QWriteLocker 自动对QReadWriteLock 加锁与解锁;

        5)QSemaphore 提供了一个整型信号量,是互斥量的泛化;

        6)QWaitCondition 提供了一种方法,使得线程可以在被另外线程唤醒之前一直休眠。

3、QThread线程类

        将应用程序的线程称为主线程,额外创建的线程称为工作线程。一般在主线程里创建工作线程,并调用start()开始执行工作线程的任务。

        QThread类的主要接口函数、信号和槽函数见下表:

关键函数说明: 

1)启动关闭函数

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

        start()会在内部调用run()函数,进入工作线程的事件循环,在run()函数里调用exit()或quit()可以结束线程的事件循环,或在主线程里调用terminate() 强制结束线程。

void run() 函数是线程体函数,用于定义线程的功能。
void start() 函数是启动函数,用于将线程入口地址设置为run函数。
void terminate() 函数用于强制结束线程,不保证数据完整性和资源释放。
void wait() 阻塞调用的线程,直到其它线程执行完毕(或者直到指定的时间过去)。

int exec() 进入事件循环并等待直到调用exit(),返回值是通过调用exit()来获得,如果调用成功则返回0。
void quit() 通知线程事件循环退出,返回0表示成功,相当于调用了QThread::exit(0)。

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

void terminate(); 结束线程,线程是否立即终止取决于操作系统。

        线程被终止时,所有等待该线程Finished的线程都将被唤醒。terminate是否调用取决于setTerminationEnabled ( bool enabled = true )开关。

2)信号量

        当线程启动和结束时,QThread会发送信号started()和finished(),可以使用isFinished()和isRunning()来查询线程的状态。从Qt4.8起,可以释放运行刚刚结束的线程对象,通过连接finished()信号到QObject::deleteLater()槽。

void started() 线程开始执行之前发射,也就是run()函数被调用之前 
void finished() 线程就要结束时发射

3)其它

        静态函数:

currentThreadId() // 返回标识当前正在执行的线程的ID 
currentThread() // 返回标识当前正在执行的线程的指针

        设置线程名称,如果不调用setObjectName(),线程的名称将是线程对象的运行时类型(QThread子类的类名):

setObjectName() // 在启动线程之前调用,用于设置线程的名称

4、创建并启动线程

执行步骤:

        1)自定义类继承自QThread;

        2)实现run()函数;

        3)主函数中定义类对象并调用start()。

#include <QCoreApplication>
#include <QThread>
#include <QDebug>

class ThreadTest: public QThread
{
public:
    ThreadTest() {}

    void run()
    {
        qDebug()<<objectName()<<" : run";
        sleep(2);
        qDebug()<<objectName()<<" : exit";
    }
};

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

    ThreadTest threada;
    threada.setObjectName(ThreadTest);
    threada.start();
    qDebug()<<"threada end";

    return a.exec();
}

结果:

传送门qt多线程系列文章目录

1、QT多线程编程详解(线程优先级):

QT多线程编程详解_coolboywjun的专栏-CSDN博客_qt多线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

jingbo1801

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

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

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

打赏作者

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

抵扣说明:

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

余额充值