UC/OS-III 消息队列

2023-05-16

消息队列

    • 一、消息队列基本概念讲解
      • 1、消息队列基本概念
      • 2、消息池
        • 2.1、消息池概念
        • 2.2、消息池初始化
        • 2.3、消息队列的运作机制
        • 2.4、消息队列的阻塞机制
        • 2.5、消息队列的应用场景
    • 二、消息队列创建步骤
      • 1、定义消息队列
      • 2、创建消息队列
    • 三、消息队列相关函数说明
      • 1、创建消息队列函数OSQCreate()
      • 2、消息队列删除函数 OSQDel()
      • 3、消息队列发送函数 OSQPost()
      • 4、 消息队列获取函数 OSQPend()
    • 四、例程

一、消息队列基本概念讲解

1、消息队列基本概念

队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、中断和任务间传递信息***(类似于裸机系统中用于传递数据用的数组)***,实现了任务接收来自其他任务或中断的不固定长度的消息。任务能够从队列里面读取消息,当队列中的消息是空时,读取消息的任务将被阻塞,用户还可以指定阻塞的任务时间 timeout,在这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效。当队列中有新消息时,被阻塞的任务会被唤醒并处理新消息;当等待的时间超过了指定的阻塞时间,即使队列中尚无有效数据,任务也会自动从阻塞态转为就绪态。消息队列是一种异步的通信方式。通过消息队列服务,任务或中断服务程序可以将消息放入消息队列中。同样,一个或多个任务可以从消息队列中获得消息。uCOS 支持先进先出原则(FIFO)以及后进先出原则(LIFO)两种模式。
uCOS 中使用队列数据结构实现任务异步通信工作,具有如下特性:
(1)、消息支持先进先出方式排队,支持异步读写工作方式(FIFO)。
(2)、消息支持后进先出方式排队,往队首发送消息(LIFO)。
(3)、读消息队列支持超时机制。
(4)、可以允许不同长度的任意类型消息(因为是引用方式传递,无论多大的数据都只是一个指针)。
(5)、一个任务能够从任意一个消息队列接收和发送消息。
(6)、多个任务能够从同一个消息队列接收和发送消息。
(7)、当队列使用结束后,可以通过删除队列函数进行删除。

2、消息池

2.1、消息池概念

在 μCOS-III 中定义了一个数组 OSCfg_MsgPool[OS_CFG_MSG_POOL_SIZE],在系统初始化OSInit() 的时候就将这个大数组的各个元素串成单向链表,组成我们说的消息池,而这些元素我们称之为消息。消息池的大小OS_CFG_MSG_POOL_SIZE 由用户自己定义,该宏定义在 os_cfg_app.h 头文件中。这样子的处理很快,并且共用了资源,系统中所有被创建的队列都可以从消息池中取出消息,挂载到自身的队列上,以表示消息队列拥有消息,当消息使用完毕,则又会被释放回到消息池中,其他队列也可以从中取出消息,这样子的消息资源是能被系统所有的消息队列反复使用。

2.2、消息池初始化

OS_MsgPoolInit() 函数就是用来初始化消息池的,OS_MsgPoolInit() 函数的定义位于os_msg.c 文件中。

2.3、消息队列的运作机制

uCOS 的消息队列控制块由多个元素组成,当消息队列被创建时,编译器会静态为消息队列分配对应的内存空间(因为我们需要自己定义一个消息队列控制块),用于保存消息队列的一些信息如队列的名字,队列可用的最大消息个数,入队指针、出队指针等。在创建成功的时候,这些内存就被占用了,创建队列的时候用户指定队列的最大消息个数,无法再次更改,每个消息空间可以存放任意类型的数据(因为采用引用方式传递,无论什么类型的多大的数据都只是一个指针)。
任务或者中断服务程序都可以给消息队列发送消息,当发送消息时,如果队列未满,uCOS 会将从消息池中取出一个消息,将消息挂载到队列的尾部,消息中的成员变量MsgPtr 指向要发送的消息。如果队列已满,则返回错误代码,入队失败。

2.4、消息队列的阻塞机制

我们使用的消息队列一般不是属于某个任务的队列,在很多时候,我们创建的队列,是每个任务都可以去对他进行读写操作,但是为了保护每个任务对它进行读操作的过程(uCOS 队列的写操作是没有阻塞的),我们必须要有阻塞机制,在某个任务对它读操作的时候,必须保证该任务能正常完成读操作,而不受后来的任务干扰。
任务对消息队列进行读操作的时候有三种阻塞状态:
(1)、不等待,队列没有消息,任务不进入阻塞态,接着干别的事情去
(2)、等待一段时间(用户设置),任务会在等待时间内接收到消息后或者超出等待时间后,退出阻塞态变成就绪态。
(3)、永久等待,任务会一直等待消息,直至完成读取队列消息,退出阻塞态,变成就绪态。
:如有多个任务阻塞在一个消息队列中,那么这些阻塞的任务将按照任务优先级进行排序,优先级高的任务将优先获得队列的访问权。如果发送消息的时候用户选择广播消息,那么在等待中的任务都会收到一样的消息。

2.5、消息队列的应用场景

消息队列可以应用于发送不定长消息的场合,包括任务与任务间的消息交换,队列是uCOS 中任务与任务间、中断与任务间主要的通讯方式,发送到队列的消息是通过引用方式实现的,这意味着队列存储的是数据的地址,我们可以通过这个地址将这个数据读取出来,这样子,无论数据量是多大,其操作时间都是一定的,只是一个指向数据地址指针。

二、消息队列创建步骤

1、定义消息队列

在app.c中定义

OS_Q queue;                             //声明消息队列

2、创建消息队列

我们使用创建消息队列函数 OSQCreate()在app.c文件中的起始任务AppTaskStart ()中创建。

		/* 创建消息队列 queue */
    OSQCreate ((OS_Q         *)&queue,            //指向消息队列的指针
               (CPU_CHAR     *)"Queue For Test",  //队列的名字
               (OS_MSG_QTY    )20,                //最多可存放消息的数目
               (OS_ERR       *)&err);             //返回错误类型

三、消息队列相关函数说明

1、创建消息队列函数OSQCreate()

创建消息队列函数,函数位于os_q.c文件中

    void OSQCreate (OS_Q *p_q,             //指向消息队列的指针
                    CPU_CHAR *p_name,      //队列的名字
                    OS_MSG_QTY max_qty,    //最多可存放消息的数目
                    OS_ERR *p_err)         //返回错误类型

2、消息队列删除函数 OSQDel()

队列删除函数是根据队列结构(队列句柄)直接删除的,删除之后这个消息队列的所有信息都会被系统清空,而且不能再次使用这个消息队列了,一般来说,在删除消息队列之前,首先要删除所有可以访问该消息队列的任务。不过,强烈建议不要在运行时删除内核对象。但是需要注意的是,如果某个消息队列没有被定义,那也是无法被删除的。想要使用消息队列删除函数就必须将OS_CFG_Q_DEL_EN 宏定义配置为 1。该宏位于os_cfg.h文件中、函数位于os_q.c文件中。

    OS_OBJ_QTY OSQDel (OS_Q *p_q,        //消息队列指针
                       OS_OPT opt,       //选项,一般用 OS_OPT_DEL_NO_PEND 选项
                       OS_ERR *p_err)    //返回错误类型
opt选项说明
OS_OPT_DEL_NO_PEND仅在没有等待消息的任务时才删除队列
OS_OPT_DEL_ALWAYS总是删除队列,而不管任务是否正在等待消息

3、消息队列发送函数 OSQPost()

任务或者中断服务程序都可以给消息队列发送消息,当发送消息时,如果队列未满,就说明运行信息入队**。uCOS 会从消息池中取出一个消息,挂载到消息队列的末尾(FIFO发送方式),如果是 LIFO 发送方式,则将消息挂载到消息队列的头部,然后将消息中MsgPtr 成员变量指向要发送的消息(此处可以理解为添加要发送的信息到消息(块)中)**,如果系统有任务阻塞在消息队列中,那么在发送了消息队列的时候,会将任务解除阻塞。

/*函数原型  opt 确定所执行发送的类型。后两个选项可以添加到任意一个OS_OPT_POST_FIFO或OS_OPT_POST_LIFO,创建不同的组合*/
    void OSQPost (OS_Q *p_q,               //消息变量指针
                  void *p_void,            //要发送的数据的指针,将内存块首地址通过队列“发送出去”
                  OS_MSG_SIZE msg_size,    //数据字节大小
                  OS_OPT opt,              //先进先出和发布给全部任务的形式
                  OS_ERR *p_err)           //返回错误类型
              
              /*函数实例 发布消息到消息队列 queue */
    OSQPost ((OS_Q   *)&queue,                             //消息变量指针
             (void   *)"Fire uC/OS-III",  //要发送的数据的指针,将内存块首地址通过队列“发送出去”
             (OS_MSG_SIZE  )sizeof ( "Fire uC/OS-III" ),     //数据字节大小
             (OS_OPT  )OS_OPT_POST_FIFO | OS_OPT_POST_ALL, //先进先出和发布给全部任务的形式
             (OS_ERR *)&err);	                            //返回错误类型
opt选项说明
OS_OPT_POST_FIFO默认采用 FIFO 方式发送
OS_OPT_POST_LIFO采用 LIFO 方式发送消息
OS_OPT_POST_1将消息发布到最高优先级的等待任务
OS_OPT_POST_ALL向所有等待的任务广播消息
OS_OPT_POST_NO_SCHED发送消息但是不进行任务调度

4、 消息队列获取函数 OSQPend()

当任务试图从队列中的获取消息时,用户可以指定一个阻塞超时时间,当且仅当消息队列中有消息的时候,任务才能获取到消息。在这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列消息有效。当其他任务或中断服务程序往其等待的队列中写入了数据,该任务将自动由阻塞态转为就绪态。当任务等待的时间超过了用户指定的阻塞时间,即使队列中尚无有效消息,任务也会自动从阻塞态转为就绪态。

/*函数原型*/
    void *OSQPend (OS_Q *p_q,                   //消息队列指针
                   OS_TICK timeout,             //等待期限(单位:时钟节拍)
                   OS_OPT opt,                  //选项
                   OS_MSG_SIZE *p_msg_size,     //返回消息大小(单位:字节)
                   CPU_TS *p_ts,                //获取等到消息时的时间戳
                   OS_ERR *p_err)               //返回错误类型
/*实例 请求消息队列 queue 的消息 */
    pMsg = OSQPend ((OS_Q         *)&queue,                //消息变量指针
                    (OS_TICK       )0,                     //等待时长为无限
                    (OS_OPT        )OS_OPT_PEND_BLOCKING,  //如果没有获取到信号量就等待
                    (OS_MSG_SIZE  *)&msg_size,             //获取消息的字节大小
                    (CPU_TS       *)0,                     //获取任务发送时的时间戳
                    (OS_ERR       *)&err);                 //返回错误
opt选项
OS_OPT_PEND_BLOCKING没有获取到信号量就等待
OS_OPT_PEND_NON_BLOCKING没有获取到信号量就也不等待

:timeout参数在指定时应该设置为0(永远等待消息)。因为使用OS_OPT_PEND_NON_BLOCKING选项时,超时值与滴答时钟不同步。

四、例程

app.c


#include <includes.h>

OS_Q queue;                             //声明消息队列

/*                                           TCB                                        */
static  OS_TCB   AppTaskStartTCB;      //任务控制块

static  OS_TCB   AppTaskPostTCB;
static  OS_TCB   AppTaskPendTCB;

/*                                  堆栈                                               */
static  CPU_STK  AppTaskStartStk[APP_TASK_START_STK_SIZE];       //任务堆栈

static  CPU_STK  AppTaskPostStk [ APP_TASK_POST_STK_SIZE ];
static  CPU_STK  AppTaskPendStk [ APP_TASK_PEND_STK_SIZE ];

/*                                   函数声明                                         */

static  void  AppTaskStart  (void *p_arg);               //任务函数声明

static  void  AppTaskPost   ( void * p_arg );
static  void  AppTaskPend   ( void * p_arg );

int  main (void)
{
    OS_ERR  err;
    OSInit(&err);                                                           //初始化 uC/OS-III
	  /* 创建起始任务 */
    OSTaskCreate((OS_TCB     *)&AppTaskStartTCB,                            //任务控制块地址
                 (CPU_CHAR   *)"App Task Start",                            //任务名称
                 (OS_TASK_PTR ) AppTaskStart,                               //任务函数
                 (void       *) 0,                                          //传递给任务函数(形参p_arg)的实参
                 (OS_PRIO     ) APP_TASK_START_PRIO,                        //任务的优先级
                 (CPU_STK    *)&AppTaskStartStk[0],                         //任务堆栈的基地址
                 (CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10,               //任务堆栈空间剩下1/10时限制其增长
                 (CPU_STK_SIZE) APP_TASK_START_STK_SIZE,                    //任务堆栈空间(单位:sizeof(CPU_STK))
                 (OS_MSG_QTY  ) 5u,                                         //任务可接收的最大消息数
                 (OS_TICK     ) 0u,                                         //任务的时间片节拍数(0表默认值OSCfg_TickRate_Hz/10)
                 (void       *) 0,                                          //任务扩展(0表不扩展)
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), //任务选项
                 (OS_ERR     *)&err);                                       //返回错误类型

    OSStart(&err);                                                          //启动多任务管理(交由uC/OS-III控制)

}

/*   起始任务  */
static  void  AppTaskStart (void *p_arg)
{
    CPU_INT32U  cpu_clk_freq;
    CPU_INT32U  cnts;
    OS_ERR      err;
    (void)p_arg;
    BSP_Init();                                                 //板级初始化
    CPU_Init();                                                 //初始化 CPU 组件(时间戳、关中断时间测量和主机名)
    cpu_clk_freq = BSP_CPU_ClkFreq();                           //获取 CPU 内核时钟频率(SysTick 工作时钟)
    cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz;        //根据用户设定的时钟节拍频率计算 SysTick 定时器的计数值
    OS_CPU_SysTickInit(cnts);                                   //调用 SysTick 初始化函数,设置定时器计数值和启动定时器
    Mem_Init();                                                 //初始化内存管理组件(堆内存池和内存池表)

#if OS_CFG_STAT_TASK_EN > 0u                                    //如果使能(默认使能)了统计任务
    OSStatTaskCPUUsageInit(&err);                               //计算没有应用任务(只有空闲任务)运行时 CPU 的(最大)
#endif                                                          //容量(决定 OS_Stat_IdleCtrMax 的值,为后面计算 CPU 
                                                                //使用率使用)。
    CPU_IntDisMeasMaxCurReset();                                //复位(清零)当前最大关中断时间
		/* 创建消息队列 queue */
    OSQCreate ((OS_Q         *)&queue,            //指向消息队列的指针
               (CPU_CHAR     *)"Queue For Test",  //队列的名字
               (OS_MSG_QTY    )20,                //最多可存放消息的数目
               (OS_ERR       *)&err);             //返回错误类型
					  
		/* 创建 AppTaskPost 任务 */
    OSTaskCreate((OS_TCB     *)&AppTaskPostTCB,                             //任务控制块地址
                 (CPU_CHAR   *)"App Task Post",                             //任务名称
                 (OS_TASK_PTR ) AppTaskPost,                                //任务函数
                 (void       *) 0,                                          //传递给任务函数(形参p_arg)的实参
                 (OS_PRIO     ) APP_TASK_POST_PRIO,                         //任务的优先级
                 (CPU_STK    *)&AppTaskPostStk[0],                          //任务堆栈的基地址
                 (CPU_STK_SIZE) APP_TASK_POST_STK_SIZE / 10,                //任务堆栈空间剩下1/10时限制其增长
                 (CPU_STK_SIZE) APP_TASK_POST_STK_SIZE,                     //任务堆栈空间(单位:sizeof(CPU_STK))
                 (OS_MSG_QTY  ) 5u,                                         //任务可接收的最大消息数
                 (OS_TICK     ) 0u,                                         //任务的时间片节拍数(0表默认值OSCfg_TickRate_Hz/10)
                 (void       *) 0,                                          //任务扩展(0表不扩展)
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), //任务选项
                 (OS_ERR     *)&err);                                       //返回错误类型

		/* 创建 AppTaskPend 任务 */
    OSTaskCreate((OS_TCB     *)&AppTaskPendTCB,                             //任务控制块地址
                 (CPU_CHAR   *)"App Task Pend",                             //任务名称
                 (OS_TASK_PTR ) AppTaskPend,                                //任务函数
                 (void       *) 0,                                          //传递给任务函数(形参p_arg)的实参
                 (OS_PRIO     ) APP_TASK_PEND_PRIO,                         //任务的优先级
                 (CPU_STK    *)&AppTaskPendStk[0],                          //任务堆栈的基地址
                 (CPU_STK_SIZE) APP_TASK_PEND_STK_SIZE / 10,                //任务堆栈空间剩下1/10时限制其增长
                 (CPU_STK_SIZE) APP_TASK_PEND_STK_SIZE,                     //任务堆栈空间(单位:sizeof(CPU_STK))
                 (OS_MSG_QTY  ) 5u,                                         //任务可接收的最大消息数
                 (OS_TICK     ) 0u,                                         //任务的时间片节拍数(0表默认值OSCfg_TickRate_Hz/10)
                 (void       *) 0,                                          //任务扩展(0表不扩展)
                 (OS_OPT      )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR), //任务选项
                 (OS_ERR     *)&err);                                       //返回错误类型
    
		OSTaskDel ( & AppTaskStartTCB, & err );                     //删除起始任务本身,该任务不再运行
		
		
}

static  void  AppTaskPost ( void * p_arg )
{
	OS_ERR      err;

	
	(void)p_arg;

					 
	while (DEF_TRUE) {                                            //任务体
		/* 发布消息到消息队列 queue */
    OSQPost ((OS_Q        *)&queue,                             //消息变量指针
             (void        *)"Fire uC/OS-III",                //要发送的数据的指针,将内存块首地址通过队列“发送出去”
             (OS_MSG_SIZE  )sizeof ( "Fire uC/OS-III" ),     //数据字节大小
             (OS_OPT       )OS_OPT_POST_FIFO | OS_OPT_POST_ALL, //先进先出和发布给全部任务的形式
             (OS_ERR      *)&err);	                            //返回错误类型
		
		OSTimeDlyHMSM ( 0, 0, 0, 500, OS_OPT_TIME_DLY, & err );     //每隔500ms发送一次
						 
	}

}

static  void  AppTaskPend ( void * p_arg )
{
	OS_ERR      err;
	OS_MSG_SIZE msg_size;
	CPU_SR_ALLOC(); //使用到临界段(在关/开中断时)时必需该宏,该宏声明和
									//定义一个局部变量,用于保存关中断前的 CPU 状态寄存器
									// SR(临界段关中断只需保存SR),开中断时将该值还原。
	char * pMsg;
	
	
	(void)p_arg;

					 
	while (DEF_TRUE) {                                       //任务体
		/* 请求消息队列 queue 的消息 */
    pMsg = OSQPend ((OS_Q         *)&queue,                //消息变量指针
                    (OS_TICK       )0,                     //等待时长为无限
                    (OS_OPT        )OS_OPT_PEND_BLOCKING,  //如果没有获取到信号量就等待
                    (OS_MSG_SIZE  *)&msg_size,             //获取消息的字节大小
                    (CPU_TS       *)0,                     //获取任务发送时的时间戳
                    (OS_ERR       *)&err);                 //返回错误
		
		if ( err == OS_ERR_NONE )                              //如果接收成功
		{
			OS_CRITICAL_ENTER();                                 //进入临界段
			
			printf ( "\r\n接收消息的长度:%d字节,内容:%s\r\n", msg_size, pMsg );

			OS_CRITICAL_EXIT();
			
		}
		
	}
	
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UC/OS-III 消息队列 的相关文章

  • FreeRTOS消息队列

    FreeRTOS消息队列 队列又称消息队列 xff0c 是一种常用于任务间通信的数据结构 xff0c 队列可以在任务与任务间 中断和任务间传递信息 xff0c 实现了任务接收来自其他任务或中断的不固定长度的消息 xff0c 任务能够从队列里
  • kafka消息队列

    1 Kafka 概念 Kafka 是一个分布式的基于发布 订阅模式的消息队列 xff08 Message Queue xff09 xff0c 主要应用于大数据实时处理领域 1 1 消息队列 应用场景 好处 1 xff09 解耦 允许你独立的
  • Springboot整合RabbitMQ

    一 Springboot整合RabbitMQ的代码实现 1 引入Springboot整合RabbitMQ的依赖
  • Rocketmq发送顺序消息

    要想保证消息的顺序性 要保证将需要保证顺序的消息按照顺序投递进一个队列中 下面演示rocketTemplate发送顺序消息 RestController RequestMapping demo public class SendContro
  • RabbitMQ高级特性-Confirm确认消息

    Confirm确认消息 消息的确认 是指生产者投递消息后 如果Broker收到消息 则会给我们产生一个应答 生产者进行接收应答 用来确定这条消息是否正常发送到Broker 这种方式也是消息的可靠性投递的核心保障 如何实现Confirm确认消
  • 如何保证消息队列的顺序性?

    面试题 如何保证消息的顺序性 面试官心理分析 其实这个也是用 MQ 的时候必问的话题 第一看看你了不了解顺序这个事儿 第二看看你有没有办法保证消息是有顺序的 这是生产系统中常见的问题 面试题剖析 我举个例子 我们以前做过一个 mysql b
  • C++ 实现一个消息队列

    文章目录 前言 一 如何实现 1 接口定义 1 推送消息 2 等待消息 3 轮询消息 2 用到的对象 1 队列 2 互斥变量 3 条件变量 3 基本流程 1 线程通信 二 完整代码 三 使用示例 1 线程通信 1 等待消息 2 轮询消息 总
  • RabbitMQ保证消息的一致性解决方案

    RabbitMQ保证消息的一致性 一 采用confirm消息确认机制及return返回机制 确保消息发送成功 二 将队列以及消息设置持久化 保证rabbitmq突然宕机消息仍然存在 三 手动确认接收消息方式 消息处理失败拒收重回队列 1 y
  • 13 SpringBoot整合RocketMQ实现过滤消息-根据SQL表达式过滤消息

    SQL表达式方式可以根据发送消息时输入的属性进行一些计算 RocketMQ的SQL表达式语法 只定义了一些基本的语法功能 数字比较 如 gt gt lt lt BETWEEN 字符比较 如 lt gt IN IS NULL or IS NO
  • RocketMQ系列之顺序消费

    前言 上节我们介绍了RMQ的两大亮点 重试和重复消费的问题 其实重试才能算亮点 重复消费最终还是要由我们自己来解决这个问题 RMQ自身并没有提供很好的机制 至少目前是没有 不知道将来会不会有 OK扯远了 今天呢 我们再来介绍RMQ一个不错的
  • kafka(一)kafka的基础与常用配置

    文章目录 一 kafka基础内容 二 kafka 中重要的参数配置 2 1 log dirs 2 2 unclean leader election enable 2 3 message max bytes 2 4 request requ
  • 12 SpringBoot整合RocketMQ实现过滤消息-根据TAG方式过滤消息

    消息发送端只能设置一个tag 消息接收端可以设置多个tag 接收消息端通过 设置多个tag 如下 tag1 tag2 tag3 上实例 生产端发送三个消息 TAG分别是TAG1 TAG2 TAG3 发送带Tag消息 测试根据Tag过滤消息
  • RabbitMQ的安装

    一 安装erlang环境 官网下载 http www erlang org downloads 这个文件其实不是gz格式的 使用file otp src 20 1 tar gz可以查看它的真实数据格式 解压 tar xvf otp src
  • RabbitMQ:Queue的介绍和使用

    1 声明 当前内容用于本人学习和使用当前的Queue 当前内容为RabbitMQ中对Queue的介绍 当前内容来源 RabbitMQ中的Queue 2 Queue的官方介绍 首先先分析以下前面的Queue的使用 其实这个东西就是一个队列 一
  • 【RabbitMQ】Consumer之消费模式、消息确认与拒绝 - 基于AMQP 0-9-1

    这篇文章主要和大家分享RabbitMQ Consumer端的知识点 主要包括Consumer的消费模式 消息是如何确认以及如何拒绝的 当消息拒绝之后 如何让消息重新进入队列 推模式 RabbitMQ支持推和拉两种消费模式 推模式就是由Bro
  • Rabbitmq入门到进阶看这篇就够了!

    安装前提 安装 erlang windows用户名非中文 可以关注我的公众号 知识追寻者 回复 rabbitmq 获取已经下载好的安装包和配套源码地址 本套教程对应知识追寻者网址 windows安装rabbitmq zszxz com Ra
  • 代码技巧——如何关闭订单?延迟任务的实现方案【建议收藏】

    先思考个问题 为什么要关闭订单 业务上 1 提供待付款时间 而不是简单的 一次付款机会 提高业务指标之一的成单率 成单率 成功下单的人数 发起支付的人数 2 下单成功意味着这个商品被当前订单占用 库存已经预扣减 如果迟迟不支付则需要回收库存
  • RocketMQ系列之架构浅谈

    RMQ的架构设计 下面我从GitHub上截取了一张RMQ的源码结构图 图中我框框出来的9大模块 基本就构成了整个RMQ的内部结构 上面9大模块的依赖层次主要如下 依赖越强的越处于底层 下面介绍下最上层的4个模块 这4个模块中工具命令行就不讲
  • RocketMQ第四篇 Rocket集群配置

    在实际开发中一般都会使用docker安装rocketMQ docker安装rocketmq如下 docker安装配置rocketmq docker安装rocketmq docker pull foxiswho rocketmq server
  • Springboot中配置activeMQ持久化

    一 activeMQ数据库持久化配置 ActiveMQ持久化的三种方式 我们采用数据库的方式来进行持久化 1 Memory 消息存储 基于内存的消息存储 2 基于日志消息存储方式 KahaDB是ActiveMQ的默认日志存储方式 它提供了容

随机推荐

  • addr2line

    1 符号表 1 1什么是符号表 符号表是内存地址与函数名 文件名 行号的映射表 符号表元素如下所示 xff1a lt 起始地址 gt lt 结束地址 gt lt 函数 gt lt 文件名 行号 gt 1 2为什么要配置符号表 为了能快速并准
  • 一些有用的Python库

    1 制作动态排序图的库 做出来像这种效果 https mp weixin qq com s DQf35t7PUcFmi3j942Q7A 2 基于matplotlib轻松绘制漂亮的表格 比自己在ppt或者excel中搞出来的表格好看多了 像这
  • Android创建杀不死的Service

    在Android开发中我们经常会遇到一些特殊的需求需要让我们的服务常驻内存 xff0c 但是会遇到各种清理软件或者用户在设置中手动停止程序的情况而导致我们的服务被异常的终止掉 虽然没有办法保证绝对的常驻内存 xff0c 但是通过策略我们还是
  • Mac 从Bash切换到Zsh的注意事项

    1 第一步要安装Zsh xff0c 可以参考现成的文章 xff0c 推荐一篇https zhuanlan zhihu com p 19556676 2 安装完成之后退出命令行重新进入 xff0c 就可以看到Zsh的效果啦 3 及得切换默认的
  • 数组求实际长度(逻辑长度)

    有很多情况下 xff0c 比如我们定义了一个数组 xff0c byte a 61 new byte 100 但是给数组赋值的时候只赋了10个 xff0c 虽然这个数组在内存中的长度仍然是100 xff0c 但是我们想得到的确实数组的实际长度
  • java清空数组

    定义一个数字byte a 61 new byte 20 如果给数组赋值后又想让数组恢复到初始的状态 xff0c 那如何做呢 xff0c 其实很简单 xff0c 直接上方法 将byte数组置空 public static byte reset
  • 使用gazebo的官方模型库文件

    首先下载所有的gazebo模型库文件 xff0c 我已经打包上传到csdn了 xff0c 可以从如下链接中下载 xff1a 下载link 然后将下载好的文件存放在如下目录 xff1a cd gazebo models 如果没有上述目录就自行
  • 作为一个普通的程序员,到底应不应该转型AI工程师?

    动不动就是50万的毕业生年薪 xff0c 动不动就是100万起步价的海归AI高级人才 xff0c 普通员到底应不应该转型AI工程师 xff0c 普通程序员到底应该如何转型AI工程师 xff1f 下面就分享几个特别典型的普通程序员成功转型AI
  • 树莓派Odroid等卡片式电脑上搭建NAS教程系列1-Ubuntu系统安装

    我用的是韩国hardkernel公司做的Odroid XU板子 xff0c 类似于树莓派香蕉派 xff0c 看下它的真面目 相关参数点他 gt Odroid XU 搭建NAS之前先来安装好Ubuntu系统 下载安装文件 在Odroid里安装
  • 立创eda学习笔记一:pcb板基础知识

    整理了一下零基础学习pcb板画图需要了解的一些基础知识 xff0c 否则后面画图很困扰 什么是pcb板 xff1f PCB xff08 Printed Circuit Board xff09 xff0c 中文名称为印制电路板 xff0c 又
  • 立创eda学习笔记二:画pcb板流程(极简入门版)

    一般PCB基本设计流程如下 xff1a 前期准备 gt PCB结构设计 gt PCB布局 gt 布线 gt 布线优化和丝印 gt 网络和DRC检查和结构检查 gt 制版 一 画原理图 完成后检查元件的封装 连线是否正确 核实电路结构 xff
  • 立创eda学习笔记十一:立创eda、立创商城、嘉立创的区别

    简单来说 xff1a 立创eda是一个画原理图和pcb的eda软件 xff0c 类似于ad 立创商城是一个卖元器件网上平台 xff0c 类似于淘宝 嘉立创是一个生产pcb板 给pcb板贴片的生产厂家 一般情况下 xff0c 你可以在立创ed
  • 立创eda学习笔记十七:铺铜

    铺铜是pcb设计很常用的指令 xff0c 或者是必然用到的指令 xff0c 很多时候布线的时候不去画gnd的线 xff0c 把其他线画好了之后 xff0c 再统一铺铜作为gnd xff0c 这样方便很多 铺铜这个概念可以理解为大面积的布线
  • 立创eda学习笔记二十六:手把手教你使用立创eda的官方教程

    可以通过以下办法找到教程 xff1a 1 xff0c 在软件界面点帮助 使用教程 2 xff0c 在网站首页 帮助 教程进入 如何使用教程 xff1a 这里是一级目录 xff0c 其实对新手最有用的是前面3个部分 xff0c 后面的仿真先不
  • 立创eda学习笔记二十四:拼板

    这里主要是两部分 xff1a 自带拼板和手动拼板 xff0c 软件自带拼板功能 xff0c 那么手动拼板当然就是自己重新画图拼板了 一般用自带拼板功能就可以了 xff0c 把单板画好之后很容易就拼好了 xff0c 完全不用动任何器件和丝印编
  • Prometheus实战教程:监控mysql数据库

    今天我们使用prometheus 43 Grafana 43 mysql exporter实现监控mysql数据库各项指标数据 mysql exporter xff1a 采集mysql数据库各项指标数据 prometheus xff1a 获
  • prometheus常用exporter下载地址大全

    1 node exporter下载 https github com prometheus node exporter releases 2 blackbox exporter下载 https github com prometheus b
  • 论文润色 ‖ 一分钟教你如何写好SCI论文里的主题句,事半功倍

    今天 xff0c 小编来分享一下论文润色 xff0c SCI论文的主题句 xff08 Topic Sentences xff09 怎么写 xff1a 01什么是主题句 xff1f 主题句通常是段落开头的一句话 xff0c 是整个段落的小主题
  • Go xml文件处理

    在开发中会常遇到xml数据序列化和反序列化 xff0c 这里我们介绍go语言处理xml数据 encoding xml 包实现了一个简单的xml 1 0解析器 xff0c 可以理解xml名称空间 读取xml 示例 xff1a package
  • UC/OS-III 消息队列

    消息队列 一 消息队列基本概念讲解1 消息队列基本概念2 消息池2 1 消息池概念2 2 消息池初始化2 3 消息队列的运作机制2 4 消息队列的阻塞机制2 5 消息队列的应用场景 二 消息队列创建步骤1 定义消息队列2 创建消息队列 三