网站后台看不到部分内容/百度推广的价格表

网站后台看不到部分内容,百度推广的价格表,新疆建设工程信息网政采云,域名怎么创建网站吗一、简介 Reactor 是运行在 JVM 上的编程框架,最大特点是完全非阻塞,能高效控制 “背压”,简单来说就是处理数据传输时速度不匹配的问题 。它能和 Java 8 里的一些功能直接搭配使用,像处理异步结果的 CompletableFuture、处理数据…

一、简介

       Reactor 是运行在 JVM 上的编程框架,最大特点是完全非阻塞,能高效控制 “背压”,简单来说就是处理数据传输时速度不匹配的问题 。它能和 Java 8 里的一些功能直接搭配使用,像处理异步结果的 CompletableFuture、处理数据序列的 Stream 以及表示时间的 Duration 等。

        在 Reactor 里,Flux 用来处理多个数据元素,Mono 处理零个或一个数据元素,并且它严格按照 “响应式扩展规范” 来设计。

        此外,reactor-ipc 这个组件可以让不同进程间在不互相等待的情况下通信。它为 HTTP(含 Websockets)、TCP 和 UDP 这些网络协议,提供了支持背压的网络引擎,很适合用在微服务架构里,还能很好地处理响应式的编解码。

响应式编程模型

二、依赖

<dependencyManagement> <dependencies><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-bom</artifactId><version>2023.0.0</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
<dependencies><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-core</artifactId> </dependency><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-test</artifactId> <scope>test</scope></dependency>
</dependencies>

三、响应式编程

        响应式编程是一种关注于数据流(data streams)变化传递(propagation of change)异步编程方式。 这意味着它可以用既有的编程语言表达静态(如数组)或动态(如事件源)的数据流。

了解历史:

        在响应式编程的发展进程中,微软率先行动,在.NET生态系统里创建了响应式扩展库(Rx)。紧接着,RxJava在JVM上实现了响应式编程。后来,JVM平台诞生了一套标准的响应式编程规范,这套规范定义了一系列标准接口和交互规则,还被整合进了Java 9(借助Flow类)。

        响应式编程常被视作面向对象编程中“观察者模式”的拓展。响应式流和“迭代子模式”也有相似之处,比如都存在类似Iterable - Iterator这样的对应关系。不过,它们的核心区别在于,Iterator采用的是“拉取”方式,也就是开发者决定何时调用next()方法获取元素,属于“命令式”编程范式;而响应式流基于“推送”方式,当有新数据产生时,由发布者(Publisher)主动通知订阅者(Subscriber),这种“推送”模式是响应式编程的关键。并且,对推送数据的处理是通过声明式的方式,即开发者只需描述“控制流程”,就能定义对数据流的处理逻辑,而不是像命令式编程那样一步步明确指令。

        在响应式流里,除了数据推送机制,错误处理和完成信号的定义也很完善。发布者(Publisher)不仅能向订阅者(Subscriber)推送新数据(调用onNext方法),还能推送错误信号(调用onError方法)和完成信号(调用onComplete方法)。一旦出现错误或完成信号,响应式流就会终止 。可以用下边的表达式描述:

onNext x 0..N [onError | onComplete]

3.1 阻塞是对资源的浪费

        现代应用面临着大量并发用户的挑战,尽管现代硬件处理能力发展迅速,但软件性能依旧是至关重要的因素。

从宏观角度看,提升程序性能主要有两种思路:

  1. 并行化:利用更多线程与硬件资源,以异步方式处理任务,借此提升整体处理效率。

  2. 优化执行效率:在现有资源的基础上,通过优化代码逻辑、算法等手段,提高单位时间内的任务处理量。

        在 Java 开发中,开发者常常采用阻塞式编程方式编写代码。这种方式本身并无不妥,当程序出现性能瓶颈时,一般会通过增加处理线程来缓解,而新增线程中的代码依旧是阻塞式的。然而,这种资源使用方式极易引发资源竞争与并发问题。

        更为严重的是,阻塞式编程会造成资源浪费。举例来讲,当程序遭遇延迟(常见于 I/O 操作,如数据库读写请求或网络调用)时,对应的线程只能进入空闲状态,等待数据返回,在此期间,线程资源被白白浪费。

        由此可见,并行化并非解决性能问题的万能良方。它虽然能够挖掘硬件潜力,但同时也带来了复杂性,并且容易造成资源浪费 。

3.2 异步可以解决问题吗

第二种思路——提高执行效率——可以解决资源浪费问题。通过编写 异步非阻塞 的代码, (任务发起异步调用后)执行过程会切换到另一个 使用同样底层资源 的活跃任务,然后等 异步调用返回结果再去处理。

但是在 JVM 上如何编写异步代码呢?Java 提供了两种异步编程方式:

  • 回调(Callbacks) :异步方法没有返回值,而是采用一个 callback 作为参数(lambda 或匿名类),当结果出来后回调这个 callback。常见的例子比如 Swings 的 EventListener。

  • Futures :异步方法 立即 返回一个 Future<T>,该异步方法要返回结果的是 T 类型,通过 Future封装。这个结果并不是 立刻 可以拿到,而是等实际处理结束才可用。比如, ExecutorService 执行 Callable<T> 任务时会返回 Future 对象。

这些技术够用吗?并非对于每个用例都是如此,两种方式都有局限性。

回调很难组合起来,因为很快就会导致代码难以理解和维护(即所谓的“回调地狱(callback hell)”)。

考虑这样一种情景:

  • 在用户界面上显示用户的5个收藏,或者如果没有任何收藏提供5个建议。

  • 这需要3个 服务(一个提供收藏的ID列表,第二个服务获取收藏内容,第三个提供建议内容):

回调地狱(Callback Hell)的例子:

userService.getFavorites(userId, new Callback<List<String>>() { public void onSuccess(List<String> list) { if (list.isEmpty()) { suggestionService.getSuggestions(new Callback<List<Favorite>>() {public void onSuccess(List<Favorite> list) { UiUtils.submitOnUiThread(() -> { list.stream().limit(5).forEach(uiList::show); });}public void onError(Throwable error) { UiUtils.errorPopup(error);}});} else {list.stream() .limit(5).forEach(favId -> favoriteService.getDetails(favId, new Callback<Favorite>() {public void onSuccess(Favorite details) {UiUtils.submitOnUiThread(() -> uiList.show(details));}public void onError(Throwable error) {UiUtils.errorPopup(error);}}));}}public void onError(Throwable error) {UiUtils.errorPopup(error);}
});

Reactor改造后:

userService.getFavorites(userId) .flatMap(favoriteService::getDetails) .switchIfEmpty(suggestionService.getSuggestions()) .take(5) .publishOn(UiUtils.uiThreadScheduler()) .subscribe(uiList::show, UiUtils::errorPopup); 

        如果你想确保“收藏的ID”的数据在800ms内获得(如果超时,从缓存中获取)呢?在基于回调的代码中, 会比较复杂。但 Reactor 中就很简单,在处理链中增加一个 timeout 的操作符即可。

userService.getFavorites(userId).timeout(Duration.ofMillis(800)) .onErrorResume(cacheService.cachedFavoritesFor(userId)) .flatMap(favoriteService::getDetails) .switchIfEmpty(suggestionService.getSuggestions()).take(5).publishOn(UiUtils.uiThreadScheduler()).subscribe(uiList::show, UiUtils::errorPopup);

额外扩展:

        Futures 比回调要好一点,但即使在 Java 8 引入了 CompletableFuture,它对于多个处理的组合仍不够好用。 编排多个 Futures 是可行的,但却不易。此外,Future 还有一个问题:当对 Future 对象最终调用 get() 方法时,仍然会导致阻塞,并且缺乏对多个值以及更进一步对错误的处理。

        考虑另外一个例子,我们首先得到 ID 的列表,然后通过它进一步获取到“对应的 name 和 statistics” 为元素的列表,整个过程用异步方式来实现。

CompletableFuture 处理组合的例子

CompletableFuture<List<String>> ids = ifhIds(); CompletableFuture<List<String>> result = ids.thenComposeAsync(l -> { Stream<CompletableFuture<String>> zip =l.stream().map(i -> { CompletableFuture<String> nameTask = ifhName(i); CompletableFuture<Integer> statTask = ifhStat(i); return nameTask.thenCombineAsync(statTask, (name, stat) -> "Name " + name + " has stats " + stat); });List<CompletableFuture<String>> combinationList = zip.collect(Collectors.toList()); CompletableFuture<String>[] combinationArray = combinationList.toArray(new CompletableFuture[combinationList.size()]);CompletableFuture<Void> allDone = CompletableFuture.allOf(combinationArray); return allDone.thenApply(v -> combinationList.stream().map(CompletableFuture::join) .collect(Collectors.toList()));
});List<String> results = result.join(); 
assertThat(results).contains("Name NameJoe has stats 103","Name NameBart has stats 104","Name NameHenry has stats 105","Name NameNicole has stats 106","Name NameABSLAJNFOAJNFOANFANSF has stats 121");

3.3 从命令式编程到响应式编程

类似 Reactor 这样的响应式库的目标就是要弥补上述“经典”的 JVM 异步方式所带来的不足, 此外还会关注一下几个方面:

  • 可编排性(Composability) 以及 可读性(Readability)

  • 使用丰富的 操作符 来处理形如 的数据

  • 订阅(subscribe) 之前什么都不会发生

  • 背压(backpressure) 具体来说即 消费者能够反向告知生产者生产内容的速度的能力

  • 高层次 (同时也是有高价值的)的抽象,从而达到 并发无关 的效果

3.3.1  可编排性与可读性

                可编排性,简单来说,就是能够有条不紊地组织多个异步任务。比如把前一个任务的成果,精准传递给下一个任务作为输入;或者像 “分而治之再汇总” 的 fork - join 模式那样,同时开展多个任务并最终整合结果;又或者把异步任务当作可复用的离散组件,在整个系统中灵活调用。

        这种任务编排能力,和代码的可读性、可维护性紧密相连。当异步处理的任务数量增多,逻辑愈发复杂,编写代码就像在荆棘丛中摸索,阅读代码更是难上加难。就拿常见的回调模式来说,它看似简单,可一旦处理逻辑复杂起来,回调里嵌套回调,一层又一层,就会陷入 “回调地狱”。经历过这种痛苦的开发者都知道,这样的代码简直是一团乱麻,想要读懂、分析清楚,实在是太费劲了。

        而 Reactor 在这方面表现出色,它提供了多种多样的编排操作。借助这些操作,代码能够清晰直观地展现处理流程,所有操作基本都维持在同一层级,尽可能避免了令人头疼的嵌套结构 。

3.3.2  就像装配流水线

        想象一下,在响应式应用里处理数据的过程,就如同产品在装配流水线上作业。Reactor就好比这条流水线的传送带,同时还充当着装配工人和机器人的角色。数据就像原材料,从源头(也就是最初的Publisher)开始流动,经过一道道工序加工,最终变成成品,等待被传送给消费者(即Subscriber)。 在这个过程中,原材料会经历各种各样的中间处理环节,可能会和其他半成品进行组装。要是流水线某个地方出现问题,比如齿轮卡住了,或者某个产品的包装耗时太长,那么这个工位就可以给上游发送信号,让它们少送点原材料过来,甚至暂停供应。

3.3.3  操作符(Operators)

       在 Reactor 中,操作符(operator)就像装配线中的工位(操作员或装配机器人)。每一个操作符 对 Publisher 进行相应的处理,然后将 Publisher 包装为一个新的 Publisher。就像一个链条, 数据源自第一个 Publisher,然后顺链条而下,在每个环节进行相应的处理。最终,一个订阅者 (Subscriber)终结这个过程请记住,在订阅者(Subscriber)订阅(subscribe)到一个 发布者(Publisher)之前,什么都不会发生。

理解了操作符会创建新的 Publisher 实例这一点,能够帮助你避免一个常见的问题, 这种问题会让你觉得处理链上的某个操作符没有起作用。

虽然响应式流规范(Reactive Streams specification)没有规定任何操作符, 类似 Reactor 这样的响应式库所带来的最大附加价值之一就是提供丰富的操作符。包括基础的转换操作, 到过滤操作,甚至复杂的编排和错误处理操作。

3.3.4  subscribe() 之前什么都不会发生

        在 Reactor 中,当你创建了一条 Publisher 处理链,数据还不会开始生成。事实上,你是创建了 一种抽象的对于异步处理流程的描述(从而方便重用和组装)。

        当真正“订阅(subscrib)”的时候,你需要将 Publisher 关联到一个 Subscriber 上,然后才会触发整个链的流动。这时候,Subscriber 会向上游发送一个 request 信号,一直到达源头的 Publisher。

3.3.5  背压

        在响应式编程里,向上游传递信号这一机制在实现背压方面发挥着关键作用。这就好比在真实的装配线上,要是某个工位处理产品的速度跟不上流水线的整体速度,它就会向上游发送反馈信号,提醒调整生产节奏。

        响应式流规范中定义的相关机制,和上述装配线的例子十分相似。订阅者在接收数据时有两种方式:一种是毫无限制地接收,任由数据源头 “开足马力”,推送所有数据;另一种则是通过 request 机制,明确告知数据源头,自己一次最多能够处理 n 个元素。

        不仅如此,中间环节的操作同样会对 request 产生影响。例如,有一种缓存(buffer)操作,它能把每 10 个元素打包成一批。这时,如果订阅者只请求 1 个元素,对于数据源头而言,其实需要生成 10 个元素,因为缓存操作是按批处理的。此外,预取策略也可以在此发挥作用,比如在订阅开始前,提前生成一些元素。

        如此一来,原本单一的 “推送” 模式,就演变成了 “推送 + 拉取” 的混合模式。下游如果已经准备就绪,便可以主动从上游拉取 n 个元素;但要是上游的元素尚未准备好,下游也只能乖乖等待上游推送 。

3.3.6  热(Hot) vs 冷(Cold)

在 Rx 家族的响应式库中,响应式流分为“热”和“冷”两种类型,区别主要在于响应式流如何 对订阅者进行响应:

  • 一个“冷”的序列,指对于每一个 Subscriber,都会收到从头开始所有的数据。如果源头 生成了一个 HTTP 请求,对于每一个订阅都会创建一个新的 HTTP 请求。

  • 一个“热”的序列,指对于一个 Subscriber,只能获取从它开始 订阅 之后 发出的数据。不过注意,有些“热”的响应式流可以缓存部分或全部历史数据。 通常意义上来说,一个“热”的响应式流,甚至在即使没有订阅者接收数据的情况下,也可以发出数据(这一点同 “Subscribe() 之前什么都不会发生”的规则有冲突)。

什么问题都可以评论区留言,看见都会回复的

如果你觉得本篇文章对你有所帮助的,把“文章有帮助的”打在评论区

多多支持吧!!!

点赞加藏评论,是对小编莫大的肯定。抱拳了!

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

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

相关文章

【Linux】Ubuntu 24.04 LTS 安装 OpenJDK 8

目录 通过 apt-get 直接安装 JDK 1. 更新 apt 软件源 2. 检查 JDK 是否已安装 3. 安装OpenJDK 4. 检查 JDK 是否成功安装 5. 设置 JAVA_HOME 环境变量 找到需要设置的 Java 路径 使用文本编辑器打开/etc/environment文件 添加 Java 安装路径 应用更改和验证配置 通过…

Linux系统管理与编程08:任务驱动综合应用

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 [环境] windows11、centos9.9.2207、zabbix6、MobaXterm、Internet环境 [要求] zabbix6.0安装环境&#xff1a;Lamp&#xff08;linux httpd mysql8.0 php&#xff09; [步骤] 3 …

数据结构之基本队列-顺序结构实现-初始化-判断队列是否为空(front=rear)-出队-入队-队尾满了,调整队列-获取队头元素

数据结构之基本队列-顺序结构实现-初始化-判断队列是否为空(frontrear)-出队-入队-队尾满了&#xff0c;调整队列-获取队头元素——完整可运行代码 #include <stdio.h>#define MAXSIZE 100 typedef int ElemType;typedef struct {ElemType data[MAXSIZE];int front;int…

基于LabVIEW的Windows平台高速闭环控制

在Windows系统下&#xff0c;通过LabVIEW实现高速闭环控制面临两大核心挑战&#xff1a;非实时操作系统的调度延迟与硬件接口的传输速度限制。以USB-6351&#xff08;NI USB-6351 DAQ卡&#xff09;为例&#xff0c;其理论采样率可达1.25 MS/s&#xff08;单通道&#xff09;&a…

【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的 RESTful API 设计:从上手到骨折

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、开篇整活…

scrapy入门(深入)

Scrapy框架简介 Scrapy是:由Python语言开发的一个快速、高层次的屏幕抓取和web抓取框架&#xff0c;用于抓取web站点并从页面中提取结构化的数据&#xff0c;只需要实现少量的代码&#xff0c;就能够快速的抓取。 新建项目 (scrapy startproject xxx)&#xff1a;新建一个新的…

FastGPT 社区版快速部署指南

产品简介 FastGPT 是基于大语言模型的智能知识库系统&#xff0c;提供以下核心能力&#xff1a; ✅ 开箱即用 - 内置数据预处理、多模型对接、权限管理 ✅ 可视化编排 - 通过 Flow 工作流实现复杂问答逻辑设计 ✅ 多场景适配 - 支持客服机器人/知识检索/数据分析等场景 &…

【css酷炫效果】纯CSS实现科技感网格背景

【css酷炫效果】纯CSS实现科技感网格背景 缘创作背景html结构css样式完整代码基础版进阶版(3D光线扫描版) 效果图 想直接拿走的老板&#xff0c;链接放在这里&#xff1a;上传后更新 缘 创作随缘&#xff0c;不定时更新。 创作背景 刚看到csdn出活动了&#xff0c;赶时间&a…

vue3:十一、主页面布局(左侧菜单折叠展开设置)

一、实现效果 二、基本实现 1、菜单容器增加展开收缩方法 在菜单容器中开启这个方法&#xff0c;值设置为一个变量 :collapseiscollapse 2、定义菜单收缩与否的变量 在js中初始化是否收缩的变量&#xff0c;初始值为不收缩(也就是展开) //左侧菜单展开与收缩 const iscolla…

Chapter 4-15. Troubleshooting Congestion in Fibre Channel Fabrics

show zone member: Shows the name of the zone to which a device belongs to. This command can be used to find the victims of a culprit device or vice versa. 显示设备所属的区域名称。该命令可用于查找罪魁祸首设备的受害者,反之亦然。 show zone active: Shows the…

网络爬虫【爬虫库request】

我叫不三不四&#xff0c;很高兴见到大家&#xff0c;欢迎一起学习交流和进步 今天来讲一讲爬虫 Requests是Python的一个很实用的HTTP客户端库&#xff0c;完全满足如今网络爬虫的需求。与Urllib对比&#xff0c;Requests不仅具备Urllib的全部功能&#xff1b;在开发使用上&…

MTKAndroid12 解决SystemUI下拉框中,长按WIFI图标会导致崩溃问题

解决SystemUI下拉框中&#xff0c;长按WIFI图标会导致崩溃问题 文章目录 场景参考资料修改文件解决方案日志源码分析 总结 场景 在部分产品中偶发性发现&#xff0c; SystemUI下拉框下拉后长按WIFI图标会导致崩溃问题&#xff0c;有时候是截屏、点击Home 按键后&#xff0c;长…

XSS基础靶场练习

目录 1. 准备靶场 2. PASS 1. Level 1&#xff1a;无过滤 源码&#xff1a; 2. level2&#xff1a;转HTML实体 htmlspecialchars简介&#xff1a; 源码 PASS 3. level3:转HTML深入 源码&#xff1a; PASS 4. level4:过滤<> 源码&#xff1a; PASS: 5. level5:过滤on 源码…

熔断降级(Sentinel解决)

问题概述 在微服务架构中一定要预防微服务雪崩问题&#xff0c;微服务雪崩问题就是指在微服务架构中&#xff0c;当一个服务出现故障时&#xff0c;由于服务之间的依赖关系&#xff0c;故障可能会传播到其他服务&#xff0c;从而导致了大规模的服务失败&#xff0c;系统无法正…

TPCTF 2025 web 复现

文章目录 baby layoutsafe layoutSafe Layout Revengesupersqli baby layout 在index.js文件中&#xff0c;看到了有使用DOMPurify库来防止XSS操作 在package.json里可以看到版本是3.2.4,关于3.2.3是有绕过策略的。它会把script标签清除掉&#xff0c;去看bot可以看到flag是放…

Agent Team 多智能体系统解析

引言 在人工智能技术高速发展的今天&#xff0c;"多智能体协作系统"&#xff08;Agent Team&#xff09;正成为突破效率瓶颈的关键技术。与传统的单体AI不同&#xff0c;这种由多个专业化智能体组成的协同网络&#xff0c;通过分工协作和动态调整&#xff0c;展现出…

bootstrap 表格插件bootstrap table 的使用经验谈!

最近在开发一个物业管理软件&#xff0c;其中用到bootstrap 的模态框。同时需要获取表格数据。用传统的方法&#xff0c;本人不想用&#xff0c;考虑到bootstrap应该有获取表格数据的方法&#xff0c;结果发现要想实现获取表格数据功能&#xff0c;需要通过bootstrap的插件实现…

循环不变量原则——螺旋矩阵

题目&#xff1a;螺旋矩阵 本题相较于螺旋矩阵II的不同之处是&#xff1a;螺旋矩阵II的矩阵是n行n列的方阵&#xff0c;而本题的矩阵并不一定是方阵。所以在遵循循环不变量原则遍历完矩阵后&#xff0c;还会有一行或者一列没有遍历。 1、行多列少&#xff08;多一列没遍历&am…

【前端】Visual Studio Code安装配置教程:下载、汉化、常用组件、基本操作

文章目录 一、Visual Studio Code下载二、汉化三、常用组件1、Auto Rename Tag2、view-in-browser3、Live Server 四、基本操作五、感谢观看&#xff01; 一、Visual Studio Code下载 下载官网&#xff1a;https://code.visualstudio.com/ 进入官网后点击右上角的Download &…

Ubuntu22.04通过DKMS包安装Intel WiFi系列适配器(网卡驱动)

下载驱动包 访问 backport-iwlwifi-dkmshttps://launchpad.net/ubuntu/source/backport-iwlwifi-dkms 网站&#xff0c;找到适用于Ubuntu 22.04的update版本&#xff08;如backport-iwlwifi-dkms_xxxx_all.deb&#xff09;&#xff0c;下载至本地。 安装驱动 在下载目录中执行以…