QT循环队列实时处理数据(二)

  上一篇多线程介绍的是,QT多线程处理机制,这篇,将对接收数据,实时处理进行分析。

         QT通过socket通信,从接收缓冲区中读取数据,交给线程进行处理,那么问题来了,如果线程还没有处理完数据,则线程就没有办法继续从缓冲区中取数,那么当数据量过大的时候,缓冲区会满,继而被覆盖,从而造成数据的丢失。那么如何将数据存储在某个特定的空间内,并且让其他线程进行读取。这个是线程通信的问题,这个问题有多种方式,一种是操作系统课本上,通过线程同步、互斥、信号量这三种机制实现线程通信,或者就是通过循环队列的方式,完成线程通信。

         这篇主要介绍的是第二种方式,即循环队列的方式,进行通信。

         循环队列的实现方式,通过全局变量定义一个大的数组,同时,定义两个读写指针,这个指针不是语言中指针这个类型,可以理解成,两个标志位,记录读和写的位置,通过这种方式,可以实现一个循环队列的基本模型。如下图:


         write表示写指针,read表示读指针。我们将从socket缓冲区接收到的数据,缓存到队列中,将写指针向后移动,另外一个线程,操作读指针,不断跟随写指针,将数据取出,处理。下面把代码贴上来供大家参考:

[cpp]  view plain  copy
  1. MyThread.h  
  2. #ifndef MYTHREAD_H  
  3. #define MYTHREAD_H  
  4.   
  5. #include <QThread>  
  6. #include <QDebug>  
  7. #include "basetype.h"  
  8. #include "mythreadstore.h"  
  9.   
  10. /** 
  11.  * @brief The MyThreadRecv class 
  12.  * 该类负责接收从tcp读取到的数据。并将数据存储到缓冲区中 
  13.  */  
  14. class MyThreadRecv  
  15. {  
  16. public:  
  17.     MyThreadRecv();  
  18.     ~MyThreadRecv(){};  
  19.   
  20.     void RecvMsg(const BYTE *data, int len);            ///< 接收数据,存入循环队列  
  21.   
  22. };  
  23.   
  24. /** 
  25.  * @brief The MyThread class 
  26.  * 处理数据的线程 
  27.  */  
  28. class MyThread: public QThread  
  29. {  
  30. public:  
  31.   
  32. public:  
  33.     MyThread();  
  34.     ~MyThread(){};  
  35.   
  36.     void init();  
  37.     void run();                 ///< 任务执行  
  38.   
  39.   
  40. private:  
  41.     volatile bool stopped;  
  42.     int Flag;  
  43.     MythreadStore *mythreadstore;  
  44. };  
  45.   
  46. #endif // MYTHREAD_H  
[cpp]  view plain  copy
  1. MyThread.cpp  
  2. #include "mythread.h"  
  3.   
  4. BYTE Queue1[(1024 * 500)] = {0};            ///< 循环消息队列  
  5. int wReadPoint = 0;                         ///< 读指针  
  6. int wWritePoint = 0;                        ///< 写指针  
  7.   
  8.   
  9. MyThreadRecv::MyThreadRecv()  
  10. {  
  11.   
  12. }  
  13.   
  14. void MyThreadRecv::RecvMsg(const BYTE *data, int len)  
  15. {  
  16.     qDebug()<<"I will gointo for";  
  17.     for(int iNum = 0; iNum < len; iNum++) {  
  18.         /** 
  19.          * @brief tempWReadPoint 
  20.          * 存储,到程序执行到此处的时候,wReadPoint的值,因为线程一直在执行,很有可能执行到这步的时候,wReadPoint的值被改变。 
  21.          */  
  22.         int tempWReadPoint = wReadPoint;  
  23.         if((wWritePoint + 1) % (1024 * 500) == tempWReadPoint) {  
  24.             /** 
  25.              * 队列已满 
  26.              */  
  27.             continue;  
  28.         }  
  29.         /** 
  30.          * 处理队列不满的情况 
  31.          */  
  32.         Queue1[wWritePoint % (1024 * 500)] = data[iNum];  
  33.         wWritePoint = (wWritePoint +1) % (1024 * 500);  
  34.   
  35.   
  36.     }  
  37.     qDebug()<<"After for";  
  38. }  
  39.   
  40. void MyThread::init()  
  41. {  
  42.     start();  
  43. }  
  44.   
  45. MyThread::MyThread()  
  46. {  
  47.     stopped = false;  
  48.     Flag = 0;  
  49.     mythreadstore = new MythreadStore();  
  50. }  
  51.   
  52. void MyThread::run()  
  53. {  
  54.     qDebug()<<"In run";  
  55.     int iFlag = 0;              ///< 标志位  
  56.     int iNum = 0;  
  57.     BYTE NeedDealdata[200] = {0};  
  58.     while(!stopped) {  
  59.         /** 
  60.          * @brief itempWritePoint 
  61.          * 存储,到程序执行到此处的时候,wWritePoint的值,因为线程一直在执行,很有可能执行到这步的时候,wWritePoint的值被改变。 
  62.          */  
  63.         int itempWritePoint = wWritePoint;  
  64.         if((wReadPoint) % (1024 * 500) != itempWritePoint) {  
  65.             /** 
  66.              * 队列不空 
  67.              */  
  68.   
  69.             if((0 != Queue1[(wReadPoint - 2) % (1024 * 500)]) && (0x5A == Queue1[(wReadPoint - 1) % (1024 * 500)]) && (0x54 == Queue1[(wReadPoint) % (1024 * 500)])) {  
  70.                 /** 
  71.                  * 找帧头 
  72.                  */  
  73.                 iNum = 0;  
  74.                 NeedDealdata[iNum++] = Queue1[(wReadPoint -1) % (1024 * 500)];  
  75.                 NeedDealdata[iNum++] = Queue1[(wReadPoint) % (1024 * 500)];  
  76.                 wReadPoint = (wReadPoint + 1) % (1024 * 500);  
  77.                 iFlag = 1;  
  78.   
  79.             }  
  80.   
  81.             if((0 != Queue1[(wReadPoint - 2) % (1024 * 500)]) && (0x5A == Queue1[(wReadPoint - 1) % (1024 * 500)]) && (0xFE == Queue1[(wReadPoint) % (1024 * 500)]) && (1 == iFlag)) {  
  82.   
  83.                 NeedDealdata[iNum++] = Queue1[(wReadPoint) % (1024 * 500)];  
  84.                 wReadPoint = (wReadPoint + 1) % (1024 * 500);  
  85.                 qDebug()<<"I will store msg || iNum = " + QString::number(iNum);  
  86.                 /** 
  87.                  * 找到需要处理的数据,处理数据 
  88.                  */  
  89.                 mythreadstore->StoreMsgDeal(NeedDealdata, iNum);  
  90.                 memset(NeedDealdata, '\0'sizeof(NeedDealdata));  
  91.   
  92.                 iFlag = 0;  
  93.                 iNum = 0;  
  94.   
  95.             }  
  96.   
  97.             if(1 == iFlag) {  
  98.                 NeedDealdata[iNum++] = Queue1[(wReadPoint) % (1024 * 500)];  
  99.                 wReadPoint = (wReadPoint + 1) % (1024 * 500);  
  100.             } else {  
  101.                 wReadPoint = (wReadPoint + 1) % (1024 * 500);  
  102.             }  
  103.   
  104.         }  
  105.         usleep(10);  
  106.   
  107.     }  
  108. }  
        上面两段代码中,存在两个类,MyThreadRecv和MyThread,前者负责存储从socket中获取到的数据,后面这个类负责从队列中读取数据,并且处理。这样的机制,能够有效的处理循环队列中的数据,从而达到实时处理数据,并且保证数据准确性和实时性的问题,但是一个重点是,需要考虑什么时候队列满,什么时候队列空,这个问题是设计这个循环队列并且处理的关键,需要根据问题仔细的去分析,然后设计。

        对于循环队列的基本内容,这里就不做详细的描述,因为比较简单,可以自行查找数据结构相关的内容。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值