反应式编程一开始是从前端和客户端开始兴起,现在大有蔓延到后端的趋势,Spring5推出的webflux就是反应式编程的产物。
webflux对比于springMVC,性能高出很多,网上已经有很多的测评,不再在过多说明。
上图看出对比于同步,异步所用的线程是比较少的,不过有个前提是,程序逻辑中有阻塞(如io阻塞等),且这种阻塞是可以异步化的。
为了满足这个前提,反应式编程框架就必须将这些阻塞变成异步化,如新出的WebClient
工具就是将http请求io异步化。
delay
方法就是用来代替sleep
方法的,下面来讲解一下delay
方法是怎么将延时异步化的。
源码解读
- 通过查看
Mono<Long> delay(Duration duration)
方法源码,它会构造一个MonoDelay
类,并通过传入全局公用的调度器Schedulers.parallel()
来调度里面的异步任务。
1 | public static Mono<Long> delay(Duration duration) { |
- 查看
MonoDelay
类的订阅方法subscribe
:
1 | public void subscribe(CoreSubscriber<? super Long> actual) { |
- 查看
ParallelScheduler
的delay方法:
1 | public Disposable schedule(Runnable task, long delay, TimeUnit unit) { |
- 查看
directSchedule
方法:
1 | static Disposable directSchedule(ScheduledExecutorService exec, |
自此就可以知道为什么delay
方法没有阻塞线程,因为它的延时处理都交给了ScheduledExecutorService
执行器处理,调用delay
方法的主线程就直接返回了,等到延时时间过后,ScheduledExecutorService
就会从线程池就获取一个线程来处理延时后的任务逻辑。整个流程就类似于上面图片中的右图。
通过反应式编程范式,将所有阻塞都修改为类似于delay
之于sleep
的形式,就能大幅度提升服务性能了。