Reactor线程调度模型

418 阅读2分钟

Scheduler 调度器

reactor 中提供了一个接口Scheduler 用于线程管理,reactor提供了一个工具类Schedulers来提供现成的调度器。本文从三个地方入手来看调度器的原理

可重用的单线程

Schedulers.newSingle()提供了一个单线程的处理器

public static Scheduler newSingle(String name, boolean daemon) {
   return newSingle(new ReactorThreadFactory(name, SingleScheduler.COUNTER, daemon,
         true, Schedulers::defaultUncaughtException));
}

public static Scheduler newSingle(ThreadFactory threadFactory) {
   final Scheduler fromFactory = factory.newSingle(threadFactory);
   fromFactory.start();
   return fromFactory;
}

default Scheduler newSingle(ThreadFactory threadFactory) {
   return new SingleScheduler(threadFactory);
}

从源码中可以看到,newSingle最后创建了一个 SingleScheduler

SingleScheduler

image.png 从代码中可以看出,start方法其实就是创建了一个单线程的线程池然后赋值给了 executor 属性,再来看另一个重要的方法 image.png

线程池创建工作对象其实是创建了一个 ExecutorServiceWorker。然后在该worker工作的时候调用的方法

image.png

image.png

publishOn

publishOn操作符能将部分运行时执行移动到指定的工作单元

Flux.range(1, 3)
          .map(i->{
              System.out.println("map 在 thread:"+Thread.currentThread().getName());
              return i;
          })
          .publishOn(Schedulers.newSingle("new thread"))
          .map(i->{
              System.out.println("map2 在 thread:"+Thread.currentThread().getName());
              return i;
          }).subscribe();

publishOn接受一个Scheduler之后的操作就都会在这个Scheduler提供的线程中执行

public final Flux<T> publishOn(Scheduler scheduler) {
   return publishOn(scheduler, Queues.SMALL_BUFFER_SIZE);
}

final Flux<T> publishOn(Scheduler scheduler, boolean delayError, int prefetch, int lowTide) {
   return onAssembly(new FluxPublishOn<>(this, scheduler, delayError, prefetch, lowTide, Queues.get(prefetch)));
}

返回的是一个FluxPublishOn, 这是一个 Operator 我们来看看其中源码

image.png 我们在之前了解 Operator 原理的时候说过这个 subscriberOrReturn 的作用是包装一个自己的subscriber返回给源头,然后在执行的时候先执行自己的监听者. 所以这里其实是返回了一个监听者

image.png 在被当成subscriber的时候其实就是创建了一个队列,然后一口气拉去256个数据,当数据来的时候先把数据丢到队列中然后调用了一个方法,我们重点看这个方法的逻辑

image.png

就是调用了worker的schedule方法,worker我们在上面已经看到了worker里面的原理.所以这个类其实还是一个runnable类.所以我们就看到底是什么方法被丢进了线程池中执行

image.png

image.png 从源码中我们了解到,方法执行到 FluxPublishOn 的时候就会进入一个线程池开始往下执行.

image.png

逻辑图如下

subscribeOn

看完了publishOn再来看看subscribeOn,看懂了publishOn后subscribeOn其实差不多

image.png 其实就是在subscribe的时候就已经传入线程池中运行了