网站首页 > java教程 正文
以前面试只问多线程,现在都开始问响应式编程了!
看完这篇文章你就能有个大体的了解了。
基本介绍
目前比较流行的编程方法论有函数式编程(functional programming)、响应式编程(reactive programming)等。
函数式编程的代表就是工作流模式,而响应式编程的代表就是reactor模式了。
reactor模式广泛地用于各种RPC框架,例如linux的epoll,redis,netty,kafka等。
事件驱动编程与多线程编程
多线程编程有如下几个缺点:
- 对于共享资源需要使用锁结构 容易造成死锁问题
- 难以Debug
- 多线程破坏了抽象 无法设计出模块化的程序
- 因为锁导致回调无法完成
- 想要得到良好的性能很难
- 线程库不受支持 很多函数不支持线程安全
事件驱动编程有以下几个特点:
- 一个执行流进程: 没有CPU的并发
- 在时间上注册消息(通过回调)
- 事件轮询等待消息, 调用处理器模型
- 时间处理器没有抢断
- 处理器通常是 短生命周期的
两者相比:
- 事件驱动编发编程尽可能的避免 并发, 而多线程编程则倾向于并发:
- 使用事件驱动更加容易调试
- 在单个CPU上时间驱动程序比线程更加快速
- 事件驱动编程更加面向接口编程
- 多线程提供了真正的并发性
Reactor模式就是一种事件驱动编程的模式,也是IO多路复用的基本设计模式。
他有如下几个特点
- Reactor模式中会通过分配适当的handler(处理程序)来响应IO事件,类似与AWT 事件处理线程;
- 每个handler执行非阻塞的操作,类似于AWT ActionListeners 事件监听
- 通过将handler绑定到事件进行管理,类似与AWT addActionListener 添加事件监听;
基本结构如下
- Handles:句柄,标识OS管理的资源.每个连接由socket句柄表示。
- Synchronous Event Demultiplexer:同步事件多路复用器,在句柄集合上阻塞等待事件的发生。
- Initiation Dispatcher:初始分发器,分发事件处理器的接口。
- Event Handler:事件处理器,指定一个由钩子方法组成的接口。
- Concrete Event Handler:具体处理事件的方法
整个流程如下:
- 我们注册Concrete Event Handler到Initiation Dispatcher中。
- Initiation Dispatcher调用每个Event Handler的get_handle接口获取其绑定的Handle。
- Initiation Dispatcher调用handle_events开始事件处理循环。在这里,Initiation Dispatcher会将步骤2获取的所有Handle都收集起来,使用Synchronous Event Demultiplexer来等待这些Handle的事件发生。
- 当某个(或某几个)Handle的事件发生时,Synchronous Event Demultiplexer通知Initiation Dispatcher。
- Initiation Dispatcher根据发生事件的Handle找出所对应的Handler。
- Initiation Dispatcher调用Handler的handle_event方法处理事件。
下面用一个例子来具体说明Reactor模式的运作:
步骤如下:
- 日志服务注册Logging Acceptor 到初始分发器来处理连接请求;
- 日志服务调用初始分发器的handle_events 方法;
- 初始分发器调用同步事件多路复用器的select 方法,等待连接请求或者日志数据的达到;
- 客户端连接到日志服务器;
- 初始分发器通知Logging Acceptor 有新连接达到;
- Logging Acceptor 接受新连接;
- Logging Acceptor 创建一个Logging Handler 来为新客户端服务;
- Logging Handler 将它的socket句柄注册到初始分发器,并且要求,当socket可读时,初始分发器通知它;
Reactor线程模型
单线程模型
多线程模型
基于多个反应器的多线程模型
Reactor模式的应用
redis(单线程模型)
Netty(多Reactor线程多Worker线程模型)
Netty的线程模式就是一个实现了Reactor模式的经典模式。
结构对应:
- NioEventLoop ———— Initiation Dispatcher
- Synchronous EventDemultiplexer ———— Selector
- Evnet Handler ———— ChannelHandle
- rConcreteEventHandler ———— 具体的ChannelHandler的实现
模式对应(Netty服务端使用了“多Reactor多线程模式”)
- mainReactor ———— bossGroup(NioEventLoopGroup) 中的某个NioEventLoop
- subReactor ———— workerGroup(NioEventLoopGroup) 中的某个NioEventLoop
- acceptor ———— ServerBootstrapAcceptor
- ThreadPool ———— 用户自定义线程池
Spring5
2年前 Java 9 发布,其中一个重要的特性就是java.util.concurrent.flow包,它规范了reactive编程中异步非阻塞流处理的背压(back pressure)问题。java8中的stream可以理解为迭代器模式(Iterator)的实现,而reactive可以理解为观察者模式(Observer)的实现。Iterator模式是服务线程去拉(pull)数据,而Observer模式是数据主动推(push)给服务线程,如果服务线程消费的太慢或者说数据推送的太快 就会引起阻塞情况 这种现象就叫做背压,java9推出了reactivestream来规范背压问题的解决方案。在Java 9之后 Spring5也All in了reactive programming,推出spring reactor包。
References
1.John Ousterhout: Why Threads Are A Bad Idea(for most purposes)
2.Douglas C. Schmidt: Reactor An Object Behavioral Pattern for Demultiplexing and Dispatching Handlers for Synchr
3. Doug Lea: Scalable IO in Java
希望能得到您的 关注、评论、转发,谢谢!
私信我“资料”,可以免费获取海量 JAVA技术栈电子书 和 大厂面试题。
猜你喜欢
- 2024-12-03 Java,JDK11,发布订阅模式,响应式流(Reactive Streams)及背压
- 2024-12-03 有空就来学Hystrix RPC保护的原理,RPC监控之滑动窗口的实现原理
- 2024-12-03 开发Spring Boot应用并部署到Minikube
- 2024-12-03 SpringWeb服务应用响应式Web开发组件:响应式编程和SpringBoot
- 2024-12-03 Reactor响应式编程 第二篇 Spring Boot 整合 Reactor 简单例子
- 2024-12-03 反应式编程之Spring Web-Flux/Project Reactor
- 2024-12-03 即学即用Kotlin - 协程
- 2024-12-03 并发编程:CompletableFuture异步编程详解
- 2024-12-03 终于有人把安卓程序员必学知识点全整理出来了,有如醍醐灌顶
- 2024-12-03 Kotlin Flow的设计精髓:响应式编程在Android中的实践
你 发表评论:
欢迎- 最近发表
-
- JAVA面试|为什么Spring Boot的jar可以直接运行?
- 什么情况,今年面试都不问八股文了??准备了几个月,结果一个都不问。。
- LangChain系列之如何使用LangChain4j构建RAG应用(1)
- JAVA入门教程-第2章 基本编程概念
- FTPC Pnuts语言(ftp mput put)
- 这9个工具库让我的Java开发效率提升了80%
- VS2022配置x86/x64调用32位和64位汇编语言动态库环境
- 别再裸写 parseFrom() 了!这才是 MQTT + Protobuf 消费的正确姿势
- aardio + Java + JavaScript 混合开发快速入门
- 铁打的程序,流水的语言,2018年JAVA编程还想坚挺500年?
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)