软件开发实践中的入队列和出队列操作的C代码示例

开发 开发工具
大家都知道,队列的特点是先入先出,即数据是按照入队列的顺序出队列的。在实际的软件开发项目中,当一个中间模块需要接收和发送大量的消息时,队列就可以大展身手了。

概述

[[178004]]

最近有在校的学生朋友在问我,数据结构中的队列在实际的软件开发项目中有什么样的用处。

大家都知道,队列的特点是先入先出,即数据是按照入队列的顺序出队列的。在实际的软件开发项目中,当一个中间模块需要接收和发送大量的消息时,队列就可以大展身手了。我们可以将接收到的数据存储在一个全局队列中,然后在另外的程序流程中将数据从同一个全局队列中取出来,经过一定的处理之后将消息发送到另外的模块。这样做可以降低程序的性能瓶颈。

本文用实际的C代码示例了简单的数据入队列和出队列的方法,大家可据此了解队列的实际用法,也可参照来实现更加复杂的队列操作。

C代码

  1. /********************************************************************** 
  2. * 版权所有 (C)2016, Zhou Zhaoxiong 
  3. * 文件名称:QueueUse.c 
  4. * 文件标识:无 
  5. * 内容摘要:示例队列的使用(入队和出队) 
  6. * 其它说明:无 
  7. * 当前版本:V1.0 
  8. * 作    者:Zhou Zhaoxiong 
  9. * 完成日期:20160811 
  10. **********************************************************************/ 
  11. #include <stdio.h> 
  12. #include <string.h> 
  13. #include <ftw.h> 
  14. #include <pthread.h> 
  15. #include <time.h> 
  16.  
  17.  
  18. // 重定义数据类型 
  19. typedef signed   int        INT32; 
  20. typedef unsigned int        UINT32; 
  21. typedef unsigned char       UINT8; 
  22.  
  23. // 宏定义 
  24. #define     MAX_QUEUE      10000          // ***队列元素个数 
  25.  
  26. // 结构体变量 
  27. typedef struct 
  28.     UINT32 iID;             // 编号 
  29.     UINT8  szInfo[100];     // 描述 
  30. } T_StructInfo; 
  31.  
  32. // 全局变量定义 
  33. T_StructInfo g_tQueue[MAX_QUEUE] = {0};      // 队列结构体 
  34. UINT32 g_iQueueHead = 0;                     // 队列头部索引 
  35. UINT32 g_iQueueTail = 0;                     // 队列尾部索引 
  36. pthread_mutex_t     g_mutex_queue_cs;        // 互斥信号量 
  37. pthread_cond_t      queue_cv; 
  38. pthread_mutexattr_t g_MutexAttr; 
  39.  
  40. // 函数声明 
  41. void PutDataIntoQueue(void); 
  42. void GetDataFromQueue(void); 
  43. INT32 EnQueue(T_StructInfo tQueueData); 
  44. INT32 DeQueue(T_StructInfo *ptStructData); 
  45. void Sleep(UINT32 iCountMs); 
  46.  
  47.  
  48. /**************************************************************** 
  49. * 功能描述: 主函数 
  50. * 输入参数: 无 
  51. * 输出参数: 无 
  52. * 返 回 值: 0-执行完成 
  53. * 其他说明: 无 
  54. * 修改日期       版本号        修改人        修改内容 
  55. ------------------------------------------------------------- 
  56. * 20160811        V1.0     Zhou Zhaoxiong     创建 
  57. ****************************************************************/ 
  58. INT32 main(void) 
  59.     pthread_mutex_init(&g_mutex_queue_cs, &g_MutexAttr); 
  60.     pthread_cond_init(&queue_cv, NULL); 
  61.  
  62.  
  63.     // 在循环中执行入队和出队操作 
  64.     while (1) 
  65.     { 
  66.         PutDataIntoQueue();  // 数据入队 
  67.  
  68.  
  69.         Sleep(5 * 1000);     // 间隔5秒 
  70.  
  71.  
  72.         GetDataFromQueue();  // 数据出队 
  73.  
  74.  
  75.         Sleep(60 * 1000);    // 每一分钟执行一次出队和入队 
  76.     } 
  77.  
  78.  
  79.     return 0; 
  80.  
  81.  
  82.  
  83.  
  84. /**************************************************************** 
  85. * 功能描述: 将数据加入队列中 
  86. * 输入参数: 无 
  87. * 输出参数: 无 
  88. * 返 回 值: 0-成功   -1-失败 
  89. * 其他说明: 无 
  90. * 修改日期       版本号        修改人        修改内容 
  91. ------------------------------------------------------------- 
  92. * 20160811        V1.0     Zhou Zhaoxiong     创建 
  93. ****************************************************************/ 
  94. void PutDataIntoQueue(void) 
  95.     T_StructInfo tQueueData = {0}; 
  96.     static UINT32 iCountNum = 0; 
  97.  
  98.  
  99.     // 对结构体的变量进行赋值 
  100.     tQueueData.iID = iCountNum; 
  101.     snprintf(tQueueData.szInfo, sizeof(tQueueData.szInfo) - 1, "zhou%d", iCountNum); 
  102.  
  103.  
  104.     // 计数值累加 
  105.     iCountNum ++; 
  106.     if (iCountNum >= MAX_QUEUE-1) 
  107.     { 
  108.         iCountNum = 0; 
  109.     } 
  110.  
  111.  
  112.     // 将数据加入队列(一直等到加入成功之后才退出) 
  113.     while (EnQueue(tQueueData) == -1) 
  114.     { 
  115.         Sleep(1000);       // 加入失败,1秒后重试 
  116.     } 
  117.  
  118.  
  119.     // 打印加入的数据 
  120.     printf("PutDataIntoQueue: ID=%d, Info=%s\n", tQueueData.iID, tQueueData.szInfo); 
  121.  
  122.  
  123.  
  124.  
  125. /**************************************************************** 
  126. * 功能描述: 将数据取出队列中 
  127. * 输入参数: 无 
  128. * 输出参数: 无 
  129. * 返 回 值: 0-成功   -1-失败 
  130. * 其他说明: 无 
  131. * 修改日期       版本号        修改人        修改内容 
  132. ------------------------------------------------------------- 
  133. * 20160811        V1.0     Zhou Zhaoxiong     创建 
  134. ****************************************************************/ 
  135. void GetDataFromQueue(void) 
  136.     T_StructInfo tQueueData = {0}; 
  137.  
  138.  
  139.     if (DeQueue(&tQueueData) == -1) 
  140.     { 
  141.         return
  142.     } 
  143.  
  144.  
  145.     // 打印取出的数据 
  146.     printf("GetDataFromQueue: ID=%d, Info=%s\n", tQueueData.iID, tQueueData.szInfo); 
  147.  
  148.  
  149.  
  150.  
  151. /**************************************************************** 
  152. * 功能描述: 数据入队列 
  153. * 输入参数: tQueueData-队列数据 
  154. * 输出参数: 无 
  155. * 返 回 值: 0-成功   -1-失败 
  156. * 其他说明: 无 
  157. * 修改日期       版本号        修改人        修改内容 
  158. ------------------------------------------------------------- 
  159. * 20160811        V1.0     Zhou Zhaoxiong     创建 
  160. ****************************************************************/ 
  161. INT32 EnQueue(T_StructInfo tQueueData) 
  162.     INT32  iRetVal  = 0; 
  163.     UINT32 iNextPos = 0; 
  164.  
  165.  
  166.     pthread_mutex_lock(&g_mutex_queue_cs); 
  167.     iNextPos = g_iQueueTail + 1; 
  168.  
  169.  
  170.     if (iNextPos >= MAX_QUEUE) 
  171.     { 
  172.         iNextPos = 0; 
  173.     } 
  174.  
  175.  
  176.     if (iNextPos == g_iQueueHead) 
  177.     { 
  178.         iRetVal = -1;   // 已达到队列的***长度 
  179.     } 
  180.     else 
  181.     { 
  182.         // 入队列 
  183.         memset(&g_tQueue[g_iQueueTail], 0x00,  sizeof(T_StructInfo)); 
  184.         memcpy(&g_tQueue[g_iQueueTail], &tQueueData, sizeof(T_StructInfo)); 
  185.  
  186.  
  187.         g_iQueueTail = iNextPos; 
  188.     } 
  189.  
  190.  
  191.     pthread_cond_signal(&queue_cv); 
  192.     pthread_mutex_unlock(&g_mutex_queue_cs); 
  193.  
  194.  
  195.     return iRetVal; 
  196.  
  197.  
  198.  
  199.  
  200. /**************************************************************** 
  201. * 功能描述: 数据出队列 
  202. * 输入参数: ptStructData-队列数据 
  203. * 输出参数: 无 
  204. * 返 回 值: 0-成功   -1-失败 
  205. * 其他说明: 无 
  206. * 修改日期       版本号        修改人        修改内容 
  207. ------------------------------------------------------------- 
  208. * 20160811        V1.0     Zhou Zhaoxiong     创建 
  209. ****************************************************************/ 
  210. INT32 DeQueue(T_StructInfo *ptStructData) 
  211.     T_StructInfo tQueueData = {0}; 
  212.  
  213.  
  214.     if (ptStructData == NULL
  215.     { 
  216.         return -1; 
  217.     } 
  218.  
  219.  
  220.     pthread_mutex_lock(&g_mutex_queue_cs); 
  221.  
  222.  
  223.     while (g_iQueueHead == g_iQueueTail) 
  224.     { 
  225.         pthread_cond_wait(&queue_cv, &g_mutex_queue_cs); 
  226.     } 
  227.  
  228.  
  229.     memset(&tQueueData, 0x00, sizeof(T_StructInfo)); 
  230.     memcpy(&tQueueData, &g_tQueue[g_iQueueHead], sizeof(T_StructInfo)); 
  231.     g_iQueueHead ++; 
  232.  
  233.  
  234.     if (g_iQueueHead >= MAX_QUEUE) 
  235.     { 
  236.         g_iQueueHead = 0; 
  237.     } 
  238.  
  239.  
  240.     pthread_mutex_unlock(&g_mutex_queue_cs); 
  241.     memcpy(ptStructData, &tQueueData, sizeof(T_StructInfo)); 
  242.  
  243.  
  244.     return 0; 
  245.  
  246.  
  247.  
  248.  
  249. /********************************************************************** 
  250. * 功能描述: 程序休眠 
  251. * 输入参数: iCountMs-休眠时间(单位:ms) 
  252. * 输出参数: 无 
  253. * 返 回 值: 无 
  254. * 其它说明: 无 
  255. * 修改日期      版本号       修改人        修改内容 
  256. ------------------------------------------------------------------ 
  257. * 20160811       V1.0     Zhou Zhaoxiong     创建 
  258. ********************************************************************/  
  259. void Sleep(UINT32 iCountMs) 
  260.     struct timeval t_timeout = {0}; 
  261.  
  262.  
  263.     if (iCountMs < 1000) 
  264.     { 
  265.         t_timeout.tv_sec  = 0; 
  266.         t_timeout.tv_usec = iCountMs * 1000; 
  267.     } 
  268.     else 
  269.     { 
  270.         t_timeout.tv_sec  = iCountMs / 1000; 
  271.         t_timeout.tv_usec = (iCountMs % 1000) * 1000; 
  272.     } 
  273.     select(0, NULLNULLNULL, &t_timeout);    // 调用select函数阻塞程序 

程序运行情况

我们将上面编写好的QueueUse.c文件上传到Linux机器上,使用“gcc -g -o QueueUseQueueUse.c”命令编译之后,生成QueueUse文件。之后,执行“QueueUse”命令,即可看到程序的运行结果(结果会不断地更新)如下:

  1. ~/zhouzx/Test/QueueUse> QueueUse  
  2. PutDataIntoQueue: ID=0, Info=zhou0  
  3. GetDataFromQueue: ID=0, Info=zhou0  
  4. PutDataIntoQueue: ID=1, Info=zhou1  
  5. GetDataFromQueue: ID=1, Info=zhou1  
  6. PutDataIntoQueue: ID=2, Info=zhou2  
  7. GetDataFromQueue: ID=2, Info=zhou2  
  8. PutDataIntoQueue: ID=3, Info=zhou3  
  9. GetDataFromQueue: ID=3, Info=zhou3 

我们看到,数据先是被加入到队列中,然后再从队列中取出来。

程序说明

***,在本程序中,入队列和出队列是在同一个函数中完成的,但是,在实际开发项目的程序中,入队列和出队列一般是在不同的程序流程(两个不同的线程)中完成的。

第二,本程序的数据入队列操作是在EnQueue函数中完成的,数据出队列操作是在DeQueue函数中完成的,全局变量g_tQueue用于存放需要处理的数据。

第三,在实际开发项目的程序中,有可能会有很多流程都会调用入队列和出队列的函数,为了防止多个流程同时向队列中加入数据或取出数据,在EnQueue和DeQueue函数中使用了锁操作。也就是说,在操作数据之前,先用pthread_mutex_lock函数执行加锁操作,在处理完数据之后,再用pthread_mutex_unlock函数执行解锁操作。

第四,在实际开发项目中,为了防止程序从队列中取数据的速率过快而使得下游模块处理不过来,我们常在从队列取出数据之后发消息的流程中控制数据的发送速率,具体每秒钟发送多少条可在配置文件中设置。

【本文是51CTO专栏作者周兆熊的原创作品,转载请通过51CTO获取作者授权】

责任编辑:武晓燕 来源: csdn博客
相关推荐

2016-12-20 11:12:11

C代码自测开发

2022-12-09 11:46:20

2023-06-09 19:01:03

软件开发

2023-06-08 16:47:09

软件开发工具

2022-08-04 10:32:04

Redis命令

2019-11-17 22:11:11

TCPSYN队列Accept队列

2021-04-23 09:00:00

开发安全编码

2023-11-03 10:33:26

2009-07-17 17:29:13

多任务多线程

2011-12-15 01:01:48

ibmdw软件开发

2009-06-12 11:35:28

模式框架软件设计

2023-02-09 16:48:12

软件开发测试结对测试

2023-08-24 09:44:16

数据库性能

2014-10-29 11:12:46

数据安全虹安

2023-12-07 12:59:46

C语言循环队列代码

2022-10-12 14:17:39

物联网软件开发

2011-08-29 11:25:29

清空service bSQL Server

2023-12-30 13:47:48

Redis消息队列机制

2024-02-02 08:25:34

队列与栈Python数据结构

2011-01-19 15:33:07

Qmail邮件队列清除
点赞
收藏

51CTO技术栈公众号