Qt 多线程

一.Qt中使用多线程的几种方法

1.继承 QThread ,重载 run 函数

2. 继承 QObject ,使用 moveToThreadQObject 对象移动到另一个线程中

3. 继承 QRunnable,使用 QThreadPool

4. 直接使用 QtConcurrent::run 写入函数和参数,自动管理线程的创建和销毁

二.实验分析

1.继承 QThread

一个 QThread 类的对象管理一个线程。通过继承 QThread 类定义线程类,并重定义 QThread 的虚函数 run(),在函数 run() 里处理线程的事件循环。

使用 start 启动线程,run() 方法一般是一个无限循环,在 run() 方法中使用 quit() 或 exit() 退出事件循环;

实验思路:编写一个多线程打印自增数字和时间以及线程id

线程类:

#include <QThread>
#include <QDebug>
#include <QDateTime>
class filetrans : public QThread
{
    Q_OBJECT
public:
    filetrans();
    void setCount(double x)//设置初始值
    {
        count=x;
    }
    void setState(bool state_)//设置打印状态
    {
        state=state_;
    }
    void run() override
    {
        while(state)//判断是否打印
        {
            QDateTime times=QDateTime::currentDateTime();
            QString timestr=times.toString("hhmmsszzz");
            qDebug()<<"当前时间:"<<timestr<<"-------------------"<<count++<<
                    "     Thread ID: " << QThread::currentThreadId();
            msleep(100);
        }
    }
private:
    double count;
    bool state=false;
};

直接在主函数中进行管理:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    create(5);//创建多线程
    for(auto thread:thread_list)
    {
        thread->setCount(2);
        thread->setState(true);//开启打印
        thread->start();//启动线程
    }
    QThread::sleep(3);
    for(auto thread:thread_list)
    {

        thread->setState(false);//关闭打印
    }
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::create(int count)
{
    for(int i=0;i<count;i++)//创建线程数组
    {
        filetrans *filetran=new filetrans();
        thread_list.push_back(filetran);

    }
}

打印结果:

结果分析:

1.通过线程 id 看出有 5 个线程,和预想结果一致

2.通过每一个打印的时间看出线程的运行是异步的

拓展:同步和异步

同步(阻塞):线程按照严格的顺序依次执行,一个线程可能需要等待另一个线程完成后才能继续执行。这种方式可以保证线程之间的数据一致性,但可能会导致程序的响应速度变慢,特别是当某些线程需要等待耗时操作完成时。

异步(非阻塞):线程可以并行执行,不需要等待其他线程完成。每个线程都可以独立执行,无需等待其他线程的结果。这种方式可以提高程序的响应速度和性能,但也需要额外考虑线程安全和数据一致性的问题。

举例分析:我要吃饭说话玩手机

同步(阻塞):只能先吃饭,再说话,接着玩手机

异步(非阻塞):边吃饭,边说话,边玩手机

2. 继承 QObject ,使用 moveToThread

实验思路:在主线程和子线程中同时打印时间

继承类:

#include <QObject>
#include <QDateTime>
#include <QThread>
#include <QDebug>
class movethread : public QObject
{
    Q_OBJECT
public:
    explicit movethread(QObject *parent = nullptr);
    void displayTime()
    {
        QDateTime times=QDateTime::currentDateTime();
        QString timestr=times.toString("hhmmsszzz");
        qDebug()<<timestr;
    }
    void run()
    {
        for(int i=0;i<5;i++)
        {
            displayTime();
            QThread::sleep(1);
        }
    }
};

主线程:

void displayTime()
{
    QDateTime times=QDateTime::currentDateTime();
    QString timestr=times.toString("hhmmsszzz");
    qDebug()<<"_______________________主线程"<<timestr;
}
void displayall()
{
    for(int i=0;i<5;i++)
    {
        displayTime();
        QThread::sleep(1);//每次休眠1秒
    }
}

QThread thread1;//创建子线程
movethread move1;//创建继承类对象
//将子线程的启动和继承类对象的run函数相连接
QObject::connect(&thread1, &QThread::started, &move1, &movethread::run);
//将类对象放到子线程中
move1.moveToThread(&thread1);
thread1.start();//启动子线程
displayall();//主线程打印开始
thread1.wait();//阻塞主线程等待子线程完成,避免主线程先结束
打印结果:

结果分析:

1.两个线程并行运行,符合预想

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值