非阻塞响应式编码

import reactor.core.publisher.Mono;  
import java.time.Duration;  
import java.util.concurrent.TimeUnit;  
  
public class ReactiveExample {  
  
    // 模拟数据处理过程,包含阻塞I/O操作  
    private static Mono<String> processData(String data) {  
        // 使用Mono.fromCallable来包装一个Callable,Callable中可以执行阻塞操作  
        // 这里我们使用Thread.sleep来模拟阻塞  
        return Mono.fromCallable(() -> {  
            // 模拟耗时的I/O操作,比如从数据库读取数据  
            try {  
                TimeUnit.SECONDS.sleep(1); // 假设这个操作耗时1秒  
            } catch (InterruptedException e) {  
                Thread.currentThread().interrupt(); // 恢复中断状态  
                throw new RuntimeException("Blocking operation interrupted", e);  
            }  
            return "Processed " + data; // 返回处理后的数据  
        })  
        .delayElement(Duration.ZERO); // 这里不需要额外的delay,因为Callable已经模拟了耗时  
    }  
  
    public static void main(String[] args) {  
        // 订阅processData返回的Mono,并打印结果  
        processData("Hello, Reactor!")  
            .subscribe(  
                result -> System.out.println(result), // 成功的回调  
                error -> System.err.println("Error: " + error.getMessage()), // 错误的回调  
                () -> System.out.println("Completed") // 完成的回调(对于Mono,这通常意味着成功完成且没有值)  
            );  
  
        // 注意:在main方法中,你可能需要添加一些代码来阻止程序立即退出,  
        // 因为异步操作可能在main方法结束之前还没有完成。  
        // 一个简单的方法是调用Thread.sleep,但这通常不是最佳实践。  
        // 在实际应用中,你可能会有一个Web服务器或长时间运行的应用程序来承载这些异步操作。  
        // 为了演示目的,我们可以添加以下代码来模拟等待:  
        try {  
            TimeUnit.SECONDS.sleep(2); // 等待足够长的时间以确保异步操作完成  
        } catch (InterruptedException e) {  
            Thread.currentThread().interrupt();  
        }  
    }  
}

### STM32非阻塞式延时函数的标准库实现 在STM32标准库开发环境中,非阻塞式的延时功能通常是通过SysTick定时器或其他硬件定时器配合标志位来实现的。这种方法不会让CPU陷入等待状态,从而可以提高程序效率并支持多任务处理。 #### SysTick定时器实现非阻塞延时 SysTick是一个常用的定时器模块,用于生成周期性的中断信号。以下是基于SysTick定时器的一个简单非阻塞延时函数的设计: 1. **初始化SysTick定时器** 使用`SysTick_Config()`函数配置SysTick定时器的时间间隔。该函数会自动设置重装载寄存器的值,并启动计数器[^4]。 ```c if (SysTick_Config(SystemCoreClock / 1000)) { // 如果返回非零,则表示SysTick配置失败 while (1); } ``` 上述代码将SysTick定时器配置为每1ms触发一次中断。 2. **定义全局变量作为延时标记** 为了跟踪当前的任务是否已经完成了指定的延时时间,需要定义一个全局变量或静态局部变量作为延时计数器。 ```c volatile uint32_t msTicks = 0; ``` 3. **编写SysTick中断服务例程(ISR)** 每次进入SysTick中断时,增加延时计数值。 ```c void SysTick_Handler(void) { msTicks++; } ``` 4. **实现非阻塞延时函数** 利用上面提到的`msTicks`变量,可以在不阻塞主线程的情况下实现延时操作。 ```c void Delay_ms(uint32_t delay) { uint32_t start_time = msTicks; while ((msTicks - start_time) < delay); // 循环直到达到设定的延迟时间 } ``` 此版本虽然实现了基本的功能需求,但由于存在轮询机制,仍可能占用一定的处理器资源。如果希望完全避免这种消耗,可进一步优化逻辑结构。 5. **改进版——事件驱动型延时控制** 对于更复杂的场景,推荐采用回调通知的方式代替持续检测。例如,在某个特定条件满足后再继续执行后续动作。 --- ### 查询法结合硬件定时器实现非阻塞延时 除了SysTick之外,还可以选用通用TIMx系列定时器完成相似目的。其优势在于能够提供更加灵活丰富的特性选项,如PWM输出、捕获比较单元等功能集成于一体化设计之中[^3]。 下面展示如何借助TIM2构建类似的解决方案: 1. 初始化TIM2外设参数; ```c RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseInitTypeDef TIM_InitStruct; TIM_InitStruct.TIM_Period = SystemCoreClock / 1000000 - 1; // 设置预分频系数使得频率接近1MHz TIM_InitStruct.TIM_Prescaler = 99; // 假定系统主频为72MHz TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_InitStruct); TIM_Cmd(TIM2, ENABLE); ``` 2. 创建独立的状态指示量; ```c volatile uint8_t timer_flag = 0; ``` 3. 编写对应的中断响应流程; ```c void TIM2_IRQHandler(void){ if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET ){ timer_flag = 1; TIM_ClearITPendingBit(TIM2,TIM_IT_Update ); } } ``` 4. 调整原有Delay接口形式如下所示; ```c void Non_Blocking_Delay_us(uint32_t us){ uint32_t count = us * (SystemCoreClock / 1000000); __disable_irq(); // 关闭总中断防止干扰 TIM_SetCounter(TIM2, 0); // 清零计数器初值 __enable_irq(); while( !timer_flag && TIM_GetCounter(TIM2)<count );// 等待超时或者外部打断 timer_flag = 0; // 复位状态以便下次调用正常工作 } ``` 以上即为一种典型应用模式下的具体编码示范说明[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Addison_Wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值