当前位置:   article > 正文

QT中的线程_qt 线程

qt 线程

QT中的线程

主线程(又称 GUI线程),负责监控窗口上的任何事件,一旦发现事件,立马处理.GUI线程只负责 UI刷新.
但是有时候,任务很耗时,GUI进程会卡住,UI无响应
这个时候创建一个新的子线程,负责处理 耗时的任务,

注意:非GUI线程禁止访问 界面上任何元素. GUI线程只负责 UI刷新.
如果非要显示,子线程要传递数据给GUI,有GUI线程负责刷新.

线程的创建:
C语言: pthread_create(thread_fun) thread_fun() {while(1){ }}
Qt提供了 QThread 类, 实现了线程功能,其中有一个方法 virtual void run() ;
就是线程执行体.

子线程类myThread 继承自QThread: 实现一个QThread子类 myThread,重写run函数即可.

  1. new 子类对象
  2. start(); 线程已经执行run函数了.

互斥锁QMutex:
我们直到,线程间 可以共享内存,于是他们之间就可以通信.
但是 如果两个线程同时访问同一个资源,就会出现问题, 解决方法—加锁

睡眠函数 静态方法QThread::msleep(int msec)

我们来了解一下互斥锁

互斥锁(同步)

在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源。这个过程有点类似于,公司部门里,我在使用着打印机打印东西的同时(还没有打印完),别人刚好也在此刻使用打印机打印东西,如果不做任何处理的话,打印出来的东西肯定是错乱的。

在线程里也有这么一把锁——互斥锁(mutex),互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即上锁( lock )和解锁( unlock )。

【互斥锁的特点】:

  1. 原子性:把一个互斥量锁定为一个原子操作,这意味着操作系统(或pthread函数库)保证了如果一个线程锁定了一个互斥量,没有其他线程在同一时间可以成功锁定这个互斥量;

  2. 唯一性:如果一个线程锁定了一个互斥量,在它解除锁定之前,没有其他线程可以锁定这个互斥量;

  3. 非繁忙等待:如果一个线程已经锁定了一个互斥量,第二个线程又试图去锁定这个互斥量,则第二个线程将被挂起(不占用任何cpu资源),直到第一个线程解除对这个互斥量的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥量。

【互斥锁的操作流程如下】:

  1. 在访问共享资源后临界区域前,对互斥锁进行加锁;

  2. 在访问完成后释放互斥锁导上的锁。在访问完成后释放互斥锁导上的锁;

  3. 对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,直到锁被释放。对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,直到锁被释放。

下面是我们老师给的图解,非常的形象

在这里插入图片描述
在这里插入图片描述

线程的演示:

两个头文件

#ifndef THREAD_H
#define THREAD_H

#include <QThread>


#include <QMutex>

struct msg {
    char temp;
    int himudity;
    int wind;
    char des[128];
};


class senderThread:public QThread {
public:

    void run() override;

    senderThread(struct msg *p,QMutex *pMutex);
    senderThread(struct msg *p);
    ~senderThread();


private:
    struct msg *pMsg;

    QMutex *pmutex;
};


class receiverThread :public QThread {
public:
    receiverThread(struct msg*p,QMutex *pMutex);
    receiverThread(struct msg *p);
    ~receiverThread();

    void run() override;

private:
    struct msg *pMsg;
    QMutex *pmutex;
};


#endif // THREAD_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "thread.h"
#include <QMutex>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

public slots:
    void btnClickedSlotFun();
private:
    Ui::Widget *ui;
    struct msg *pMsg;
    QMutex  Mutex;

    class senderThread *pSendThread;
    class receiverThread *pRecvThread;
};
#endif // WIDGET_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

线程文件

#include "thread.h"

#include <cstdio>
#include <QDebug>

void senderThread::run()
{
    static int cnt= 0;
    while(1){
        cnt++;

        pmutex->lock(); //使用之前加锁,注意 如果发现锁已经被锁上了, 则进程睡眠等待唤醒

        pMsg->temp = (char)cnt;
        QThread::msleep(1000);
        pMsg->himudity=cnt*11;
        QThread::msleep(1000);
        pMsg->wind = cnt+100;
        QThread::msleep(1000);
        snprintf(pMsg->des,sizeof(pMsg->des),"sunday,tmp=%d hm=%d win=%d.",pMsg->temp,pMsg->himudity,pMsg->wind);
        pmutex->unlock();   //使用之后解锁, 也会唤醒其他等待的进程
    }
}

senderThread::senderThread(msg *p, QMutex *pMutex)
{
    pMsg=p;
    pmutex = pMutex;
}


senderThread::senderThread(msg *p)
{
    pMsg=p;
}

senderThread::~senderThread()
{

}

receiverThread::receiverThread(msg *p, QMutex *pMutex)
{
    pMsg=p;
    pmutex = pMutex;
}

receiverThread::receiverThread(msg *p)
{
    pMsg=p;
}

receiverThread::~receiverThread()
{

}

void receiverThread::run()
{
    while(1){
        pmutex->lock();
        qDebug()<<"tmp:"<< int(pMsg->temp)<<" hm:"<<pMsg->himudity<<" win="<<pMsg->wind<<" des:"<<pMsg->des;
        pmutex->unlock();
        QThread::sleep(1);

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //创建两个线程共享的空间
      pMsg = new    struct msg;
      memset(pMsg,0,sizeof(struct msg));
      pSendThread = new senderThread(pMsg,&Mutex);
      pRecvThread = new receiverThread(pMsg,&Mutex);
      pSendThread->start();
      pRecvThread->start();
      connect(ui->btntest,SIGNAL(clicked()),this,SLOT(   btnClickedSlotFun()     ));
  }

Widget::~Widget()
{
    delete ui;
     delete  pMsg;
}
void Widget::btnClickedSlotFun()
{
    QString str = QString("temp=%1 hm=%2 wind=%3 des:%4").arg(int(pMsg->temp)).arg(pMsg->himudity).arg(pMsg->wind).arg(pMsg->des);
    ui->textEdit->setText(str);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

运行后我们得到的是这个效果:

在这里插入图片描述

在加锁以后我们写入的数据就不会被覆盖掉,就可以得到我们需要的数据了

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/104560
推荐阅读
相关标签
  

闽ICP备14008679号