步入响应式编程篇(一)

news2025/1/17 11:00:57

响应式编程

  • 为什么要有响应式编程?
  • 响应式编程的用法
  • Flow api的用法
    • 处理器

为什么要有响应式编程?

传统编码,操作流程常见的是命令式编程范式,如对于一个请求或操作来说,都是串行执行,直到异常或执行结束;
这种方式的优点是简洁明了,逻辑清晰,但缺点也很明显,性能问题严重
如果一个接口里的逻辑是先查DB,再请求第三方接口,这两步操作都是阻塞操作,需要耗费大量IO时间。于是可以使用CompletableFuture编排异步线程来优化这两步操作,这样主线程就可以释放CPU时间片了(实现了主线程的异步),这种方式叫做部分响应式编程。而且在查DB和访问第三方接口,各自维护一个异步线程,都有IO阻塞,为了解决这个问题,就要使用非阻塞的方式,而NIO就叩开了非阻塞的大门,其连接、读、写都是非阻塞的,只需一个线程就可以处理以上两步骤,节省JVM维护多个线程的成本。所以编排异步线程+非阻塞的方式就是完全响应式编程

命令式编程和响应式编程都是一种编程范式;
编程范式是指编程语言的设计和使用方式;

响应式编程的用法

接口操作一般就是对方法的调用,
而命令式编程的步骤,一般就是定义入参,处理业务,再异常或返回;
而响应式编程,是基于Stream流,可看做水流,简单来说,是定义流源头,然后往下流,使用链式处理多个步骤,最后流向最后,就是异常或响应信号。
响应式编程的落地实现有Flow api、Reactor api,Spring WebFlux;

Flow api的用法

从Java 9开始就提供了响应式编程的API,叫做Flow。它实际上是拷贝了Reactive Stream的四个接口定义,然后放在juc包的Flow类中。具体实现是通过SubmissionPublisher和ConsumerSubscriber两个默认实现;

package org.example.flux;

import java.io.IOException;
import java.util.concurrent.Flow;
import java.util.concurrent.SubmissionPublisher;

/**
 * @date: 2025/1/16 18:29
 * @author: lvan
 * @description: 使用Flow的api
 */
public class FlowApiDemo {

    public static void main(String[] args) throws IOException, InterruptedException {
        //发布者,就是流的源头
        SubmissionPublisher<String> publisher  =new SubmissionPublisher();

        //定义订阅者
        Flow.Subscriber<String> subscriber = new Flow.Subscriber<String>() {

            Flow.Subscription subscription = null;
            @Override
            public void onSubscribe(Flow.Subscription subscription) {
                System.out.println(Thread.currentThread().getName()+"开始订阅时触发onSubscribe……");
                this.subscription = subscription;
                //向发布者发送一个信号,代表订阅者已经准备好
                subscription.request(1);
            }

            @Override
            public void onNext(String item) {
                System.out.println(Thread.currentThread().getName()+"接收从发布者的下一个元素时触发的onNext……");
                System.out.println("订阅者接收"+item);
                //背压模式,每次告诉发布者只发送一个
                /*try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }*/
                subscription.request(1);

            }

            @Override
            public void onError(Throwable throwable) {
                System.out.println("接收发布者的错误时触发onError……"+throwable.getMessage());
            }

            @Override
            public void onComplete() {
                System.out.println("流正常结束的信号onComplete……");
            }
        };
        //订阅者订阅发布者
        publisher.subscribe(subscriber);
        //发布者发布
        for (int i=0;i<10;i++) {

            publisher.submit("test"+i);
            System.out.println("发布者发送了一个后开始休眠一秒");
 /*           Thread.sleep(1000);
            if (i==7){
                throw new RuntimeException("报异常……");
            }*/
        }
        publisher.close();

        //因为发布订阅是异步的,所以不要让主线程停止,避免程序结束
        System.in.read();
    }
}

运行效果:
在这里插入图片描述

其实注释得很清晰了,定义发布者和订阅者后,注意:
①要订阅者订阅发布者后,且要request()发送一个信号给发布者,告诉它流程已准备好,开启异步线程接收到发布者发布的数据,否则发布者只是发送到一个缓冲区数组中;
②注意订阅者每次onNext接收发布者的消息时,可以通过背压模式控制接收能力,也就是调request(),如果不调该方法,就代表不再接收消息了;

背压模式的思想是大量请求过来,是发送到缓冲区,然后线程根据自己的消费能力往缓冲区中获取,这就是背压模式

③注意发布者和订阅者定义的泛型,都是String,也就是说要发送和接收的类型要一致才能成功接收;

处理器

还可在发布者和订阅者之间定义处理器,因为前面也说过,响应式编程就像是流,定义了数据源头后,中间可被多个步骤进行处理;可看做处理器作为发布者的订阅者,作为订阅者的发布者:

package org.example.flux;

import java.util.concurrent.Flow;
import java.util.concurrent.SubmissionPublisher;

/**
 * @date: 2025/1/16 18:38
 * @author: lvan
 * @description: TODO
 */
public class FlowApiProcessor extends SubmissionPublisher<String> implements Flow.Processor<String,String> {

    Flow.Subscription subscription = null;

    @Override
    public void subscribe(Flow.Subscriber subscriber) {
    }

    @Override
    public void onSubscribe(Flow.Subscription subscription) {
        System.out.println("处理器订阅触发onSubscribe……");
        this.subscription =subscription;
        subscription.request(1);
    }

    @Override
    public void onNext(String item) {
        System.out.println("作为中间操作,处理数据触发onNext……");
        item="hello,Flow Api_"+item;
        //作为发布者发送数据
        submit(item);
        subscription.request(1);
    }

    @Override
    public void onError(Throwable throwable) {

    }

    @Override
    public void onComplete() {

    }
}

还需在订阅关系那里改一下:

//处理器订阅发布者
FlowApiProcessor flowApiProcessor = new FlowApiProcessor();
publisher.subscribe(flowApiProcessor);
//订阅者订阅处理器
publisher.subscribe(subscriber);

如有需要收藏的看官,顺便也用发财的小手点点赞哈,如有错漏,也欢迎各位在评论区评论!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2277977.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++—18、C++ 中如何写类

一、类的功能阐述 今天我们将用目前学到的类的基础知识从头开始编写一个类。只编写一个基本的Log类&#xff0c;来演示到目前为止我们学过的一些基本特性。随着接下来的学习你会看到从一个类的基本版本到一个更高级版本的过程和区别。高级版本可以做同样的事情&#xff0c;但可…

SW - 查看装配图中的零件的全路径名称

文章目录 SW - 查看装配图中的零件的全路径名称概述笔记END SW - 查看装配图中的零件的全路径名称 概述 装配图中&#xff0c;如果本机有多个不同版本的同名零件(e.g. v1/p1零件, v2/p1零件)&#xff0c;在装配图中想确认是哪个版本的零件。 如果编辑错了文件&#xff0c;或者…

【开源分享】nlohmann C++ JSON解析库

文章目录 1. Nlohmann JSON 库介绍2. 编译和使用2.1 获取库2.2 包含头文件2.3 使用示例2.4 编译 3. 优势4. 缺点5. 总结参考 1. Nlohmann JSON 库介绍 Nlohmann JSON 是一个用于 C 的现代 JSON 库&#xff0c;由 Niels Lohmann 开发。它以易用性和高性能著称&#xff0c;支持 …

神经网络基础-正则化方法

文章目录 1. 什么是正则化2. 正则化方法2.1 Dropout正则化2.2 批量归一化(BN层) 学习目标&#xff1a; 知道正则化的作用掌握随机失活 DropOut 策略知道 BN 层的作用 1. 什么是正则化 在设计机器学习算法时希望在新样本上的泛化能力强。许多机器学习算法都采用相关的策略来减小…

【C++】面试题整理(未完待续)

【C】面试题整理 文章目录 一、概述二、C基础2.1 - 指针在 32 位和 64 位系统中的长度2.2 - 数组和指针2.3 - 结构体对齐补齐2.4 - 头文件包含2.5 - 堆和栈的区别2.6 - 宏函数比较两个数值的大小2.7 - 冒泡排序2.8 - 菱形继承的内存布局2.9 - 继承重写2.10 - 如何禁止类在栈上分…

ASP.NET Core - 依赖注入(四)

ASP.NET Core - 依赖注入&#xff08;四&#xff09; 4. ASP.NET Core默认服务5. 依赖注入配置变形 4. ASP.NET Core默认服务 之前讲了中间件&#xff0c;实际上一个中间件要正常进行工作&#xff0c;通常需要许多的服务配合进行&#xff0c;而中间件中的服务自然也是通过 Ioc…

w~Transformer~合集11

我自己的原文哦~ https://blog.51cto.com/whaosoft/12472192 #LightSeq 最高加速9倍&#xff01;字节跳动开源8比特混合精度Transformer引擎,近年来&#xff0c;Transformer 已经成为了 NLP 和 CV 等领域的主流模型&#xff0c;但庞大的模型参数限制了它的高效训练和推理。…

海云安开发者安全智能助手D10荣膺 “ AI标杆产品 ” 称号,首席科学家齐大伟博士入选2024年度 “ 十大杰出青年 ”

2024年12月27日&#xff0c;粤港澳大湾区AI领袖峰会在深圳成功举办&#xff0c;大会表彰了在人工智能技术创新、应用实践和产业发展等方面取得优异成绩的企业和个人&#xff0c;深圳海云安网络安全技术有限公司开发者安全智能助手D10荣膺“AI标杆产品”称号。同时&#xff0c;公…

Autodl转发端口,在本地机器上运行Autodl服务器中的ipynb文件

通过 SSH 隧道将远程端口转发到本地机器 输入服务器示例的SSH指令和密码&#xff0c;将远程的6006端口代理到本地 在服务器终端&#xff0c;激活conda虚拟环境 conda activate posecnnexport PYOPENGL_PLATFORMegljupyter notebook --no-browser --port6006 --allow-root从…

网站建设公司哪家好?我的避坑指南

公司刚成立那个时候&#xff0c;第一步就是想着抓紧做一个官网&#xff0c;因为一个好的网站可以通过互联网源源不断的带来客流&#xff0c;所以小公司业务最重要&#xff0c;我就赶紧在网上开始找公司。 网站是的大活&#xff0c;对于我这种什么都不会的&#xff0c;当然只能…

浅谈云计算15 | 存储可靠性技术(RAID)

存储可靠性技术 一、存储可靠性需求1.1 数据完整性1.2 数据可用性1.3 故障容错性 二、传统RAID技术剖析2.1 RAID 02.2 RAID 12.3 RAID 52.4 RAID 62.5 RAID 10 三、RAID 2.0技术3.1 RAID 2.0技术原理3.1.1 两层虚拟化管理模式3.1.2 数据分布与重构 3.2 RAID 2.0技术优势3.2.1 自…

qml RadialGradient详解

1、概述 RadialGradient是QML中用于创建径向渐变效果的一种类型。它允许您定义从中心向外辐射的颜色渐变&#xff0c;可以应用于各种QML可视组件上&#xff0c;如Rectangle、Image等&#xff0c;以创建出丰富的视觉效果。 2、重要属性 angle&#xff1a;定义渐变围绕其中心点…

链表 -- 反转链表,k个一组翻转链表,两两交换链表中结点

目录 反转链表 题目 ​编辑 分析 代码 k个一组翻转链表 题目 分析 代码 两两交换链表中的结点 题目 ​编辑 分析 代码 反转链表 题目 分析 反转过程: newhead作为遍历指针,最终停在尾结点上prev保存上一个结点,通过改变newhead和prev的连接来实现反转(核心)通过ne…

mac配置 iTerm2 使用lrzsz与服务器传输文件

mac配置 1. 安装支持rz和sz命令的lrzsz brew install lrzsz2. 下载iterm2-send-zmodem.sh和iterm2-recv-zmodem.sh两个脚本 # 克隆仓库 git clone https://github.com/aikuyun/iterm2-zmodem ~/iterm2-zmodem# 进入到仓库目录 cd ~/iterm2-zmodem# 设置脚本文件可执行权限 c…

统计学习算法——决策树

内容来自B站Up主&#xff1a;风中摇曳的小萝卜https://www.bilibili.com/video/BV1ar4y137GD&#xff0c;仅为个人学习所用。 问题引入 有15位客户向某银行申请贷款&#xff0c;下面是他们的一些基本信息&#xff0c;类别列表示是否通过贷款申请&#xff0c;是表示通过贷款申…

疫苗预约小程序ssm+论文源码调试讲解

第4章 系统设计 一个成功设计的系统在内容上必定是丰富的&#xff0c;在系统外观或系统功能上必定是对用户友好的。所以为了提升系统的价值&#xff0c;吸引更多的访问者访问系统&#xff0c;以及让来访用户可以花费更多时间停留在系统上&#xff0c;则表明该系统设计得比较专…

物联网网关Web服务器--lighttpd服务器部署与应用测试

以下是在国产ARM处理器E2000飞腾派开发板上部署 lighttpd 并进行 CGI 应用开发的步骤&#xff1a; 1、lighttpd简介 Lighttpd 是一款轻量级的开源 Web 服务器软件&#xff0c;具有以下特点和功能&#xff1a; 特点 轻量级&#xff1a;Lighttpd 在设计上注重轻量级和高效性&a…

Linux的常用命令(三)

目录 六、网络通信命令 1.网络通信命令ping 2.网络通信命令ifconfig 七、系统命令 1. 系统命令shutdown 2. 系统命令reboot 八、vi编辑器 六、网络通信命令 1.网络通信命令ping 命令名称&#xff1a;ping 命令所在路径&#xff1a;/usr/sbin/ping 执行权限&#xff…

CryptoMamba:利用状态空间模型实现精确的比特币价格预测

“CryptoMamba: Leveraging State Space Models for Accurate Bitcoin Price Prediction” 论文地址&#xff1a;https://arxiv.org/pdf/2501.01010 Github地址&#xff1a;https://github.com/MShahabSepehri/CryptoMamba 摘要 预测比特币价格由于市场的高波动性和复杂的非线…

【图表示例】元素-边-01

G6A Graph Visualization Framework in JavaScripthttps://g6.antv.antgroup.com/zh/examples/element/edge/#line 项目的创建参考 G6 详细教程&#xff0c;注意&#xff0c;node版本需要&#xff1a;required: { node: >18 }G6A Graph Visualization Framework in JavaScri…