Project Reactor源码分析-subscribeOn

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

相关示例源码: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操作符的消费阶段实现简单,都是直接将元素下发给下游。

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

相关推荐

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

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

Zong_0915的博客 4632

Project Reactor源码阅读-flatMap

super T,?将外部Publisher发射出来的元素转换成内部Publisher,然后将这些内部的Publisher合并到一个Flux中,允许元素交错。mapper:转换函数,将外部Publisher发射出来的元素转换成一个新的Publisher。:针对外部Publisher的最大请求数量,同时也是队列大小。可通过属性配置,默认32。prefetch:针对内部Publisher的最大请求数量,同时也是innerQueue队列大小。可通过属性配置,默认256。

老男孩的架构路 795

Project Reactor 深度解析 随记

一、Project Reactor 深度解析 - 1. 响应式编程介绍,实现以及现有问题 随记: 1、响应式编程框架:RxJava 、 Project Reactor、Vert.x 以及 java 9 引入的响应式编程的标准接口Flow 2、什么是响应式编程 1)、传统编程存在两个问题:一个问题是:一个请求一个线程,是阻塞式调用,高并发时,如果一个IO线程阻塞的时间比较长,有可能导致线程池所有的线程都处于阻塞状态,这样就没法处理请求了。另一个问题是:一个请求要并行处理时,写代码比较麻烦。 2)、基于回调的C

山巅 1586

Spring5中Reactor编程的Mono与Flux类源码解读

Spring5的函数式编程使用了ProjectReactor工程的类,使用最为多的就是Mono和Flux类型,其中Mono是针对0到1个元素进行操作,Flux是针对多个元素进行操作。要使用这两个类前提是自己要有jdk8,Lambda,函数式编程的基础,否则请先学习了以上知识再来接触Spring5的Mono和FLux。 我们针对Mono类的一行代码,来进行源码分析与讲解。代码如下: Mono.......

lz710117239的博客 2万+

Netty源码_02_Netty中的Reactor源码解析

netty最核心的就是reactor线程,对应项目中使用广泛的NioEventLoop,那么NioEventLoop里面到底在干些什么事?netty是如何保证事件循环的高效轮询和任务的及时执行?又是如何来优雅地fix掉jdk的nio bug?带着这些疑问,本篇文章将庖丁解牛,带你逐步了解netty reactor线程的真相[源码基于4.1.6.Final] reactor 线程的启动 NioEventLoop的run方法是reactor线程的主体,在第一次添加任务的时候被启动 NioEventLoop 父

毛毛的专栏 1748

projectreactor.io:React堆公共网站

项目React堆网站 这是Project Reactor主页的源代码。 它还作为如何在单个项目中使用Spring Web Reactive Framework,Reactor和其他Web技术的示例应用程序。 您可以通过运行以下命令启动应用程序: $ ./gradlew run 要启用实时重载静态资源(包括.scss文件),请在应用程序仍在运行时运行以下命令: $ ./gradlew processResources -t 要打包应用程序,包括Javadoc,请执行以下操作: $ ./gradlew clean build shadowJar 确保您至少具有IntelliJ IDEA 2016.2.5和Kotlin插件1.1-M02, build.gradle.kts自动完成build.gradle.kts和验证。 您可能必须在以下位置配置EAP更新站点:工具-> Kotlin->配

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

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

weixin_34199335的博客 405

MRI图像切片(nii格式转2D)

代码参考:将一个MRI(nii格式)数据进行切片 想要批量抽取MRI数据的几个切片,借鉴了上述代码的Python版本,原始代码抽取了全部切片。本次实验主要是抽取sMRI的横断面(axial)方向的其中30张切片,数量根据自己需求可自行设置。 import scipy, numpy, shutil, os, nibabel import sys, getopt import imageio def niito2D(filepath): inputfiles = os.listdir(filep

chs_502的博客 7552

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

详解k-means++

一、概述 定义:k-means++是一种为k-means聚类算法选择初始值(或“种子”)的算法。它是NP-hard k-means问题的一种近似算法,它是一种避免标准k-means算法有时发现的较弱聚类的方法。 K-means与K-means++:原始K-means算法最开始随机选取数据集中K个点作为聚类中心,而K-means++按照如下的思想选取K个聚类中心:假设已经选取了n个初始聚类中心(0<n<K),则在选取第n+1个聚类中心时:距离当前n个聚类中心越远的点会有更高的概率被选为第n+1个聚

qq_42364307的博客 3万+

新手必看:电路设计里的‘地’到底怎么接?单点、多点、混合接地保姆级图解

本文深入解析电路设计中的接地技术,涵盖单点、多点和混合接地的原理与应用。通过详细的图解和实战案例,帮助新手理解接地在提供参考电位、构成电流回路及抑制电磁干扰中的关键作用,避免常见设计误区,提升电路稳定性与抗干扰能力。

weixin_28455801的博客 301

Project Reactor源码阅读-Scheduler

Reacor在进行线程切换()以及并行计算(runOn)都会使用Scheduler。通过前面的源码分析,我们知道对于SchedulerWorker。本文主要分析各种Scheduler实现原理。

老男孩的架构路 894

博途PLC S7-1200/1500 ModbusTcp通信SCL代码篇(轮询)

博途PLC MODBUS TCP的详细讲解和注意事项,可以参看下面这篇博文,这里不在赘述。这篇作为SCL代码篇主要给出SCL语言下的轮训写法和注意事项。博途PLC1200/1500PLC ModbusTcp通信(轮询处理)_RXXW_Dor的博客-优快云博客。............

RXXW_Dor的博客 8430

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

基于Simulink的间接功率控制的矩阵变换器

通过上述步骤,我们成功设计并实现了基于 Simulink 的间接功率控制的矩阵变换器仿真模型。该模型能够通过控制输入电流和输出电压,实现对功率的间接控制,适用于电机驱动、可再生能源系统、电力传输等领域。通过虚拟场景仿真、参数优化和性能评估,验证了系统的稳定性和高效性,并通过调整 PI 控制器参数和优化调制算法,进一步提升了系统的性能。

MHD0815的博客 297

国社科基金申报书“选题与说明依据”用AI怎么写?借助Gemini 3 Pro一次理清研究演进逻辑

研究进展部分要明确指出已有研究的不足与局限,比如方法不足、数据或材料受限、研究视角单一等等局限,之后要找准研究切入点,自然引申出自己的研究问题。为提升课题申报书的质量,学术史梳理要遵循述评结合、中外结合、新老结合的原则,不仅“述”,更要“评”,兼顾国内研究与国际学术动态,统筹经典研究与最新成果。它是对选题的整体概述,需阐明研究的具体问题、视角以及核心概念。2)存在问题或争议:结合已有研究或实践现状,指出该领域在理论建构、测量工具、实践应用或研究结论方面仍存在的不足、空白或争议,明确研究的必要性;

智能AI让学术科研更容易 943

Project Reactor源码阅读-concat

将多个Publisher按顺序拼接起来,并向下游转发这些Publisher发射出来的元素,通过依次订阅实现。

m0_57042151的博客 326

嵌入式工程师成长之路(5)——板子调试

USB2514集线器调试总结说说USB连接线USB数据线上的“疙瘩”:原来有这么大用处!

云轩阁 4万+

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

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

七夜zippoe的博客 1838

Linux 内核参数:meminfo

内存管理是一个相对复杂的内核模块,错综复杂的数据结构和管理逻辑。Linux 内核为了帮助开发者从宏观上把握内存的使用情况,在几大核心数据结构中都有相应的计数统计,如物理页面使用情况、伙伴系统分配情况、内存管理区的页面使用情况、内存回收扫描回收情况、内存规整触发情况等等。本文要分析的节点meminfo是Linux 操作系统中查看系统内存最准确(meminfo 中有内存黑洞)的方法,它包含当前时刻系统的所有物理页面的信息。

私房菜 2417

老版QQ原生表情gif动态

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

reactor3 源码分析

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

刘本龙的专栏 9291

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Project Reactor原理解读

Java Project Reactor原理解读

qq_31918513的博客 1042

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Java ProjectReactor 响应式编程 Mono 简单工作流程解析

本文通过自己实现接口的方式,揭示了响应式编程核心类 Mono 的基本原理。其核心接口为三个 Publisher,Subscriber,Subsription。核心方法为 Publisher#onSubscribe(Subscription),Subscriber#onSubscribe(Subscription),Subsription#request(long), Subscriber#onNext(T)

huachangzai的博客 1万+

InnoDB 内存结构总览:Change Buffer、AHI 与 Log Buffer

本文系统梳理InnoDB内存结构中的ChangeBuffer、Adaptive Hash Index(AHI)与LogBuffer。ChangeBuffer缓存二级索引页不在内存时的变更,减少随机IO,仅在页加载时合并;聚簇索引修改立即执行,因数据本身不可延后。AHI基于高频等值查询自动构建哈希索引,加速定位,仅支持等值操作。LogBuffer为redo log内存缓冲,配合磁盘日志实现崩溃恢复。三者均服务于性能优化,其中ChangeBuffer与AHI共享BufferPool空间,而LogBuffer独立

bksczm的博客 304
上一篇: 20年清华扫地僧,整理的Storm、Spark学习笔记,面试官:给我看看
下一篇: 10w条数据仅需2秒,浅谈MyBatis批量插入方法
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值