Qt编程技巧总结篇(5)-信号-槽-多线程(四)

Qt编程技巧总结篇(5)-信号-槽-多线程(四)

  多线程学习,使用QSemaphore提供线程同步方法, 信号量(Semaphore)是一种限制对共享资源进行访问的线程同步机制。与互斥量的区别是,信号量可以多次使用,而互斥量只能被锁定一次。 信号量常用来保护一定数量的相同资源,如数据采集时的双缓冲区。OK,开整~

QSemaphore提供的函数

  • acquire(int n) 尝试获得n个资源,如果没有阻塞到有n个资源;
  • release(int n) 释放n个资源,信号资源全部可用后再release;
  • int available() 返回当前信号量可用的资源个数;
  • bool tryAcquire(int n=1) 尝试获取n个资源,不成功时不阻塞线程。

实例与应用

下面的例子是《 QT5.9 c++ 开发指南》中的例子,代码放这里,欢迎参考学习!

qmythread.h 文件中定义了两个线程,其中QThreadDAQ线程负责将采集的数据放入缓冲区,QThreadShow线程负责读取缓冲区的数据并显示。很有趣的交互方式,两个缓冲区进行读写操作,又称双缓冲读取方式。

#ifndef QMYTHREAD_H
#define QMYTHREAD_H

//#include    <QObject>
#include    <QThread>

class QThreadDAQ : public QThread
{
    Q_OBJECT

private:
    bool    m_stop=false; //停止线程
protected:
    void    run() Q_DECL_OVERRIDE;
public:
    QThreadDAQ();
    void    stopThread();
};

class QThreadShow : public QThread
{
    Q_OBJECT
private:
    bool    m_stop=false; //停止线程
protected:
    void    run() Q_DECL_OVERRIDE;
public:
    QThreadShow();
    void    stopThread();
signals:
    void    newValue(int *data,int count, int seq);
};
#endif // QMYTHREAD_H

qmythread.cpp 文件中重写两个线程的run()函数

#include    "qmythread.h"
#include    <QSemaphore>

const int BufferSize = 8;
int buffer1[BufferSize];
int buffer2[BufferSize];
int curBuf=1; //当前正在写入的Buffer

int bufNo=0; //采集的缓冲区序号

quint8   counter=0;//数据生成器

/* ***
 * 信号量(Semaphore)是一种限制对共享资源进行访问的线程同步机制。
 * 与互斥量的区别是,信号量可以多次使用,而互斥量只能被锁定一次。
 * 信号量常用来保护一定数量的相同资源,如数据采集时的双缓冲区。
 * 几个函数:
 * acquire(int n)           尝试获得n个资源,如果没有阻塞到有n个资源;
 * release(int n)           释放n个资源,信号资源全部可用后再release;
 * int available()          返回当前信号量可用的资源个数;
 * bool tryAcquire(int n=1) 尝试获取n个资源,不成功时不阻塞线程。
*/

QSemaphore emptyBufs(2);//信号量:空的缓冲区个数,初始资源个数为2
QSemaphore fullBufs; //满的缓冲区个数,初始资源为0

QThreadDAQ::QThreadDAQ()
{

}

void QThreadDAQ::stopThread()
{
    m_stop=true;
}

void QThreadDAQ::run()
{
    m_stop=false;//启动线程时令m_stop=false
    bufNo=0;//缓冲区序号
    curBuf=1; //当前写入使用的缓冲区
    counter=0;//数据生成器

    int n=emptyBufs.available();
    if (n<2)  //保证 线程启动时emptyBufs.available==2
      emptyBufs.release(2-n);

    while(!m_stop)//循环主体
    {
        emptyBufs.acquire();//获取一个空的缓冲区
        for(int i=0;i<BufferSize;i++) //产生一个缓冲区的数据
        {
            if (curBuf==1)
                buffer1[i]=counter; //向缓冲区写入数据
            else
                buffer2[i]=counter;
            counter++; //模拟数据采集卡产生数据

            msleep(50); //每50ms产生一个数
        }

        bufNo++;//缓冲区序号
        if (curBuf==1) // 切换当前写入缓冲区
          curBuf=2;
        else
          curBuf=1;

        fullBufs.release(); //有了一个满的缓冲区,available==1
    }
    quit();
}

void QThreadShow::run()
{
    m_stop=false;//启动线程时令m_stop=false0

    int n=fullBufs.available();
    if (n>0)
       fullBufs.acquire(n); //将fullBufs可用资源个数初始化为0

    while(!m_stop)//循环主体
    {
        fullBufs.acquire(); //等待有缓冲区满,当fullBufs.available==0阻塞

        int bufferData[BufferSize];
        int seq=bufNo;

        if(curBuf==1) //当前在写入的缓冲区是1,那么满的缓冲区是2
            for (int i=0;i<BufferSize;i++)
               bufferData[i]=buffer2[i]; //快速拷贝缓冲区数据
        else
            for (int i=0;i<BufferSize;i++)
               bufferData[i]=buffer1[i];

        emptyBufs.release();//释放一个空缓冲区
        emit    newValue(bufferData,BufferSize,seq);//给主线程传递数据
    }
    quit();
}

QThreadShow::QThreadShow()
{

}

void QThreadShow::stopThread()
{
    m_stop=true;
}

小结

  多线程的学习就更新到这里了,实现多线程的方式在这几篇文章中主要是 QMutexQWaitCondition以及QSemaphore这几种方式,灵活运用,多写多练,前路未卜,仍需奋力前行!加油,共勉。

相关推荐

  1. Qt编程技巧总结5)-信号--线

    2024-07-21 16:22:03       18 阅读
  2. Qt编程技巧总结(4)-信号--线(三)

    2024-07-21 16:22:03       21 阅读
  3. 力学笃行(Qt 线信号

    2024-07-21 16:22:03       20 阅读
  4. QT基础(12)QT5线

    2024-07-21 16:22:03       41 阅读
  5. QT(6.5) cmake构建C++编程线

    2024-07-21 16:22:03       30 阅读
  6. Qt线编程(QThread)

    2024-07-21 16:22:03       22 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 16:22:03       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 16:22:03       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 16:22:03       45 阅读
  4. Python语言-面向对象

    2024-07-21 16:22:03       55 阅读

热门阅读

  1. cannot import name ‘OrderedDict‘ from ‘typing‘

    2024-07-21 16:22:03       15 阅读
  2. GFS分布式文件系统

    2024-07-21 16:22:03       15 阅读
  3. 牛客暑假训练2 C.Red Walking on Grid

    2024-07-21 16:22:03       17 阅读
  4. Python之后端Django(六)

    2024-07-21 16:22:03       13 阅读
  5. blender和3dmax和maya和c4d比较

    2024-07-21 16:22:03       17 阅读
  6. 数据结构第33节 在不同领域的应用

    2024-07-21 16:22:03       13 阅读
  7. 【软考】UML中的关联关系

    2024-07-21 16:22:03       20 阅读
  8. firefly rk3288 ubuntu23.10 网卡名为end0 改为eth0

    2024-07-21 16:22:03       15 阅读
  9. C++狼人杀游戏(真的能运行!!!)

    2024-07-21 16:22:03       14 阅读
  10. 跨平台游戏引擎 Axmol-2.1.4 发布

    2024-07-21 16:22:03       21 阅读
  11. 使用 hutool工具实现导入导出功能。

    2024-07-21 16:22:03       21 阅读
  12. https证书申请

    2024-07-21 16:22:03       18 阅读