Project Reactor源码分析-subscribeOn

Reactor响应式编程系列(六)- 解读subscribeOn()方法 阅读详情

相关示例源码:github.com/chentianmin…

功能分析

public final Flux<T> subscribeOn(Scheduler scheduler, boolean requestOnSeparateThread)
复制代码

在subscribe的时候进行线程切换,subscribeOn()使得它上游的订阅阶段以及整个消费阶段异步执行。

各参数含义如下:

  1. scheduler:线程切换的调度器,Scheduler用来生成实际执行异步任务的Worker。
  2. requestOnSeparateThread:是否需要在Worker上执行request()请求,默认true。在慢Publisher、快Consumer场景中可能导致长时间阻塞,可将requestOnSeparateThread设置成false解决这个问题。

代码示例

@Test
public void testBlock() {
    delayPublishFlux(1000, 1, 10)
            .doOnRequest(i -> logLong(i, "request"))
            .subscribeOn(Schedulers.newElastic("subscribeOn"))
            .publishOn(Schedulers.newElastic("publishOn"), 2)
            .subscribe(i -> logInt(i, "消费"));
    sleep(10000);
}
复制代码

 在红框时间段内,消费者被阻塞了!

将requestOnSeparateThread设置成false:恢复正常 

下面我们从源码角度分析subscribeOn()操作符,顺便探究一下上述问题发生的原因。

源码分析

首先看一下subscribeOn()操作符在装配阶段做了什么,直接查看Flux#subscribeOn()源码。

Flux#subscribeOn()

 装配阶段重点是创建了FluxSubscribeOn对象,该类同样实现了OptimizableOperator接口。

在分析publishOn()的时候,我们已经知道此时在subscribe()阶段会调用FluxSubscribeOn#subscribeOrReturn()方法。

FluxSubscribeOn#subscribeOrReturn()

  1. 创建了SubscribeOnSubscriber对象,它同时是一个任务。
  2. 在当前线程调用下游onSubscribe()方法。
  3. 使用Woker异步执行SubscribeOnSubscriber任务,实际执行SubscribeOnSubscriber#run()方法。

SubscribeOnSubscriber#run()

 继续调用了上游的Publisher#subscribe()方法,执行订阅。后续肯定会调用到SubscribeOnSubscriber#onSubscribe()方法。

SubscribeOnSubscriber#onSubscribe()

 重点是调用了requestUpstream()方法。实际上,在request()中,也可能调用requestUpstream()。

SubscribeOnSubscriber#requestUpstream()

 这里的重点是:由当前线程还是Worker向上游请求数据。

  1. requestOnSeparateThread=false:肯定由当前线程执行。
  2. requestOnSeparateThread=true:取决于当前线程是否与执行subscribe()操作是同一线程。

对于前面的例子,requestOnSeparateThread=true时:

  1. 执行onSubscribe()方法时,当前线程与执行subscribe()操作是同一线程,直接由当前线程继续向上游请求数据。
  2. 执行request()方法时,当前线程变成了publishOn线程,此时由Worker向上游请求数据。而问题正是出现这里,当前的Worker还在生产数据,新提交的任务根本没有线程来执行。request被阻塞住,下游的消费者自然不会消费数据。

这其实还跟elasticScheduler(弹性线程池)有关,它底层是由单线程池组成的,下一篇文章会深入分析。

requestOnSeparateThread=false时,由当前线程(publishOn)继续向上游请求数据,因此不会造成阻塞。

消费阶段

subscribeOn操作符的消费阶段实现简单,都是直接将元素下发给下游。

Reactor响应式编程系列(五)- 解读publishOn()方法 阅读详情

相关推荐

Project Reactor源码分析系列 - SpscLinkedArrayQueue原理分析

之前做reactive streaming的调研,在回压的场景中,都会用到Queue。 周末的时候又有人问到Queue的实现原理,但是印象比较模糊,现在来具体的分析一下,Project Reactor对传统Queue的优化。 当然RxJava也是用到的同样的Queue的实现。 类说明与注释 final class SpscLinkedArrayQueue&lt;T&gt; extends Abst...

rickey17的博客 1561

Reactor3 源码解析八: FluxSubscribeOn源码剖析

Flux.just("tom", "jack", "allen") .filter(s -> s.length() > 3) .doOnNext(s -> { System.out.println("producter: " + Thread.currentThread().getName() + " " + s); }) .subscribeOn(Schedulers.parallel()) ...

八荒六合唯我独尊 1236

视觉惯性SLAM系列——ORB-SLAM3的整体介绍及各个线程的功能(五)

跟踪线程(Tracking Thread)作用:负责处理每一帧图像,进行相机位姿的估计和定位。它首先执行与前一帧图像的特征匹配,然后通过仅运动(motion-only)BA(Bundle Adjustment)优化位姿。如果跟踪失败,它会尝试在所有地图中进行重定位。此外,跟踪线程还负责决定何时插入新的关键帧,以及何时将关键帧从局部地图中移除。详细介绍见局部建图线程(Local Mapping Thread)作用:管理局部地图,向活跃地图添加关键帧和点,移除多余的关键帧和点。

曾经也曾立志 1004

reactor3 源码分析

文章目录概述本文需要知识点观察者模式lambda表达式reactor源码分析 概述 Reactor 用于创建高效的响应式系统。Reactor 是一个用于JVM的完全非阻塞的响应式编程框架,具备高效的需求管理(即对 “背压(backpressure)”的控制)能力。它与 Java 8 函数式 API 直接集成,比如 CompletableFuture, Stream, 以及 Duration。它提供...

刘本龙的专栏 9291

修复zookeeper未授权访问漏洞

【代码】修复zookeeper未授权访问漏洞。

qq_28392947的博客 4069

MIMO技术入门

MIMO:多天线技术,发射端和接收端有多个天线(注意:并不是指多个天线板,而是多套振子,每一套是一个独立的天线。) 4G:2、8天线 5G:4、64天线(64T64R) 手机也是多天线 MIMO实现效果的分类: 1)空间分集 。2)空间复用。3)波束赋形。 空间分集(space diversity) 作用:提升接收质量 利用多个天线发射或者接收一个数据流,避免单个信道衰落对整个链路的影响。(比如你的耳机坏了一只并不影响另一只) 空间复用(space multiplexing) 作用:提升速率 利

About1129的博客 2877

Reactor3 源码解析七: FluxPublishOn源码剖析(2)

Flux.create(emitter -> { for (int i = 0; i <= 20; i++) { if (emitter.isCancelled()) { return; } System.out.println(Thread.currentThread().getName() + ":Source created " + i); emitter.next(i); } }).doOnNext(s -...

八荒六合唯我独尊 697

基于python+flask框架的基于微信小程序的CR公司建设项目信息管理系统-前台(开题+程序+论文) 计算机毕设

特别是随着移动互联网技术的普及,企业对便捷、高效的信息管理系统的需求日益迫切。另一方面,该系统集成了仓管、物料、财务、人事、供应商等多个模块,实现了数据的集中管理和信息共享,有助于企业实现精细化管理,降低运营成本,提升决策效率。:深入调研CR公司的业务需求,明确系统应具备的功能模块,包括仓管员管理模块(物料信息、退回记录、申请信息、仓库信息管理)、财务员管理模块(资金信息管理、采购与租赁款项处理)、人事管理模块、供应商管理模块、项目管理模块(项目信息、设备采购、物料采购、设备租赁)、以及考勤打卡模块等。

zhihao503的博客 960

Java中级开发面试核心:并发编程与JVM调优实战

并发编程是Java开发的核心技能,涉及线程安全、锁优化等关键技术。通过synchronized和ReentrantLock等机制实现线程同步,其底层原理涉及JVM monitor和AQS队列。JVM调优则关注内存管理、垃圾回收策略等,合理配置参数可显著提升系统性能。这些技术在电商秒杀、金融交易等高并发场景中尤为重要。本文结合面试真题,深入解析Java并发编程三大核心问题与JVM性能调优实战要点,帮助开发者掌握系统设计关键能力。

weixin_34199335的博客 405

fMRI数据处理:从DICOM到NIFTI(下)

上一篇我们完成了对原始DICOM的数据整理,将其整理为了BIDS目录结构。作为从从DICOM到NIFTI的最后一篇,当然是介绍如何批量将DICOM格式转NIFTI格式啦!从DICOM到NIFTI系列就完成啦!撒花★,°.°★。从核磁机器把数据拷回来——到整理成BIDS格式——到批量转格式;我们fMRI数据处理的第一步就算是正式迈出去啦!接下来的内容,敬请期待吧~

weixin_44933894的博客 2080

【openGauss实战1】openGauss基于CentOS8的部署

基于openGauss数据库在CentOS8上的安装实践。

IT邦德 3053

响应式编程基石 Project Reactor源码解读

《深入解析Project Reactor:响应式编程的核心原理与实践》 摘要:本文深入剖析了Java响应式编程框架Project Reactor的核心实现机制。通过分析Mono和Flux的设计理念、订阅机制、操作符链、线程调度和背压控制等关键组件,揭示了响应式编程的底层原理。文章结合性能测试数据,展示了不同场景下的优化策略,并提供了API网关等实战案例。特别强调背压机制作为响应式编程的灵魂,以及常见的内存泄漏、线程阻塞等问题的解决方案。最后指出,响应式编程需要深入理解其原理才能发挥最大价值,建议开发者从简单

七夜zippoe的博客 1838

【目标检测】IoU(交并比)详解及代码实现

1. IOU概述        IoU的全称为交并比(Intersection over Union),是目标检测中使用的一个概念,IoU计算的是“预测的边框”和“真实的边框”的交叠率-,即它们的交集和并集的比值。最理想情况是完全重叠,即比值为1。 2. IoU计算        IoU等于“预测的边框”和“真实的边框”之间交集和并集的比值。IoU计算如下图,B1为真实

Roaddd的博客 2万+

Project Reactor 核心原理解析

一、开篇 本文将解析 Spring 的 Reactor 项目的源码。主要目的是让自己能深入理解 Reactor 这个项目,以及 Spring 5 和 Spring Boot 2。 Project Reactor 项目地址:https://github.com/reactor Reactor 项目主要包含 Reactor Core 和 Reactor Netty 两部分。Reactor Core 实现了反应式编程的核心功能,Reactor Netty 则是 Spring WebFlux 等技术的基础。本

八荒六合唯我独尊 4561

科技英语/专业英语——改错总结【2】

1.固定句式 make it + adj + 句子 例:These features make the electronic systems difficult to intercept this kind of signal. 正确形式:These features make it  difficult for the electronic systems  to intercept

MISAYAONE的博客 1732

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Java响应式编程Reactor

在onNext方法中,我们使用map操作算子将订单转换为需要请求的风控信息,然后使用filter操作算子对风险评估结果进行筛选,并使用flatMap操作算子向风控服务发送请求获取评估结果。接下来,我们需要实现消费者和操作算子。假设我们有一个订单系统,需要实现以下功能:当有新订单产生时,根据订单金额判断是否需要进行风险评估。在这个例子中,我们首先创建了一个订单发布者和一个订单处理器,并将它们连接起来。它提供了可观察的序列流和操作算子,允许开发人员按照事件流的方式编写代码,而不是按照传统的控制流方式。

M先生的博客 1097

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Java Reactor学习

三、publishOn 与 subscribeOn 接下来进入正题。先看两个例子(来自 https://github.com/reactor/lite-rx-api-hands-on) publishOn 的例子 Mono<Void> fluxToBlockingRepository(Flux<User> flux, BlockingRepository<User> repositor.

u011976751的博客 327

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Project Reactor 之 publishOn 与 subscribeOn

为什么80%的码农都做不了架构师?>>> ...

weixin_34128501的博客 839

publishOn Vs subscribeOn 在 Project Reactor 3 的使用区别

publishOn Vs subscribeOn 在 Project Reactor 3 的使用区别使用区分与差异 使用 如何使用publishOn和subscribeOn public class publishOnVsSubscribeOn { public static Flux comSubscribeOn(){ return Flux.just(1, 2, 3, 4) .subscribeOn(Schedulers.parallel())

alexdyysp的博客 898

Android线程详解

现在大多数的移动设备已经变得越来越快,但是它们其实也不算是非常快。如果你想让你的APP既可以承受一些繁杂的工作而又不影响用户体验的话,那么必须把任务并行执行。在Android上,我们使用线程。 端一杯咖啡,然后仔细阅读这篇文章。我会给大家介绍一下线程的概念,还有在Java中怎么使用线程,在线程中怎么使用Handler等。 如果需要使用异步处理或者并行任务的话,那么你一定会用到线程。

switch(mind) 2万+

Reactor 3 Reference Guide - 选译 (2)

Reactor Core Features Programmatically creating a sequence 本节介绍如何程序化增加Flux和Mono,以及相关事件(onNext、onError和onComplete)。这些方法都触发了称为sink的事件。实际上是sink的变种。 Synchronous generate 程序化增加Flux的最简单办法是generate方法,接受一个gen...

weixin_43364172的博客 987

Project Reactor展开方法

最近,我的一位同事向我介绍了Project Reactor类型的expand运算符,在这篇文章中,我想介绍几种使用它的方式。 展开分页结果 考虑在名为City的模型上基于Spring Data的存储库: import org.springframework.data.jpa.repository.JpaRepository; import samples.geo.domain.Cit...

最佳 Java 编程 734

Reactor中 publishOn 与 subscribeOn的区别

publishOn 和 subscribeOn publishOn 和 subscribeOn。这两个方法的作用是指定执行 Reactive Streaming 的 Scheduler(可理解为线程池), 不过这两个方法是用的场景是不相同的. 为何需要指定执行 Scheduler 呢?一个显而易见的原因是:组成一个反应式流的代码有快有慢,可能你的下游接口RT是不同的。如果将这些功能都放在一个线程里...

coderlong的博客 6854
上一篇: 一次夜间接口超时的解决过程
下一篇: 读时加写锁,写时加读锁,Eureka可真的会玩
java小姜在线冲
博客等级 码龄4年 53粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值