RxJava github 地址:https://github.com/ReactiveX/RxJava/tree/2.x
RxJava 相关概念和一些用法这里不再赘述,可以查看官方文档 官方文档 以及其他的一些博客,闲话少说,这里直接从 rx 的 github 中简单用法去深入源码解读。
这篇分析 rx 的线程切换,废话不多说,直接上代码
val currentTimeMillis = System.currentTimeMillis()
Flowable.fromCallable<Any> {
println("时间间隔:" + (System.currentTimeMillis() - currentTimeMillis) + " , 所在线程:" + Thread.currentThread())
Thread.sleep(1000) // imitate expensive computation
println("时间间隔:" + (System.currentTimeMillis() - currentTimeMillis) + " , 所在线程:" + Thread.currentThread())
"Done"
}
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.single())
.subscribe({ x: Any? ->
println("时间间隔:" + (System.currentTimeMillis() - currentTimeMillis) + " , 所在线程:" + Thread.currentThread())
println(x)
}) { obj: Throwable ->
obj.printStackTrace()
}
这段代码会输出什么呢?
时间间隔:41 , 所在线程:Thread[RxCachedThreadScheduler-1,5,main]
时间间隔:1042 , 所在线程:Thread[RxCachedThreadScheduler-1,5,main]
时间间隔:1043 , 所在线程:Thread[RxSingleScheduler-1,5,main]
Done
为什么 fromCallable 在 Cached 线程,而打印却在 Single 线程呢?进入源码先看下 subscribeOn
首先了解下 Schedulers.io()
public static Scheduler io() {
return RxJavaPlugins.onIoScheduler(IO);
}
IO 在静态代码块中初始化,如下
static final Scheduler IO;
static {
//
//走IOTask的回调
IO = RxJavaPlugins.initIoScheduler(new IOTask());
//
}
调用到 IOTask
static final class IOTask implements Callable<Scheduler> {
@Override
public Scheduler call() throws Exception {
return IoHolder.DEFAULT;
}
}
static final class IoHolder {
static final Scheduler DEFAULT = new IoScheduler();
}
public IoScheduler() {
this(WORKER_THREAD_FACTORY);
}
public IoScheduler(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
this.pool = new AtomicReference<CachedWorkerPool>(NONE);
start();
}
IoScheduler 的 start 中调用 Executors.newScheduledThreadPool(1, EVICTOR_THREAD_FACTORY); 创建了线程池
Schedulers.single() 同理,不过创建的线程池不一样,这里不追究下去。因此便有了 IO 和 SINGLE 两种线程池。
接下来查看 subscribeOn
public final Flowable<T> subscribeOn(@NonNull Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return subscribeOn(scheduler, !(this instanceof FlowableCreate));
}
public final Flowable<T> subscribeOn(@NonNull Scheduler scheduler, boolean requestOn) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new FlowableSubscribeOn<T>(this, scheduler, requestOn));
}
将有 IO 线程池的 scheduler 传入,并且判断之前创建的 Flowable 是否为 FlowableCreate,将三个参数封装成 FlowableSubscribeOn 对象内。
同理,observeOn 中将由 SINGLE 线程池的 scheduler 封装成 FlowableObserveOn。
我们直接看 FlowableObserveOn 的 subscribeActual 方法做了什么
public void subscribeActual(Subscriber<? super T> s) {
Worker worker = scheduler.createWorker();
if (s instanceof ConditionalSubscriber) {
source.subscribe(new ObserveOnConditionalSubscriber<T>(
(ConditionalSubscriber<? super T>) s, worker, delayError, prefetch));
} else {
source.subscribe(new ObserveOnSubscriber<T>(s, worker, delayError, prefetch));
}
}
这里第一行的 createWorker 方法与之前的操作符不同了,重点关注下,它是个接口
public Worker createWorker() {
return new ScheduledWorker(executor.get());
}
创建了对象那个 ScheduledWorker,它也是个 Disposable。
将参数 ScheduledWorker 封装成为 ObserveOnSubscriber ,并使用 LambdaSubscriber 订阅。
FlowableSubscribeOn 的 subscribeActual 方法
public void subscribeActual(final Subscriber<? super T> s) {
Scheduler.Worker w = scheduler.createWorker();
final SubscribeOnSubscriber<T> sos = new SubscribeOnSubscriber<T>(s, w, source, nonScheduledRequests);
s.onSubscribe(sos);
w.schedule(sos);
}
首先,第一行代码中,FlowableSubscribeOn 创建了 EventLoopWorker
public Worker createWorker() {
return new EventLoopWorker(pool.get());
}
第二行,将参数封装到 SubscribeOnSubscriber 中。
第三行,onSubscribe 意味着 subscribeOn 与上两篇创建性操作符 just、range 有些类似了,要开始创建数据了。但是它没有数据源呀,带着疑问继续。
经过上篇分析,自然到了最下面创建的 FlowableObserveOn 的内部类 ObserveOnSubscriber 或父类中的 request 方法
public final void request(long n) {
if (SubscriptionHelper.validate(n)) {
BackpressureHelper.add(requested, n);
trySchedule();
}
}
final void trySchedule() {
if (getAndIncrement() != 0) {
return;
}
worker.schedule(this);
}
这边调用 SINGLE 创建出来的 ScheduledWorker 的 schedule 方法,将自身 ObserveOnSubscriber (实现也实现了 Runnable )传进入。
public Disposable schedule(@NonNull Runnable run) {
return schedule(run, 0L, TimeUnit.NANOSECONDS);
}
public Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
//判断
//Hook
//
f = executor.submit((Callable<Object>)sr);
//
}
将 ObserveOnSubscriber 加到 SINGLE 线程池中了
第四行代码,调用 IO 创建出来的 ScheduledWorker 的 schedule 方法,将自身SubscribeOnSubscriber(也实现了 Runnable )传进入,自然也是加入线程池。
先看下 ObserveOnSubscriber 的 run
void runAsync() {
final Subscriber<? super T> a = downstream;
final SimpleQueue<T> q = queue;
for (;;) {
long r = requested.get();
while (e != r) {
boolean d = done;
T v;
try {
v = q.poll();
} catch (Throwable ex) {
}
boolean empty = v == null;
if (empty) {
break;
}
a.onNext(v);
e++;
if (e == limit) {
if (r != Long.MAX_VALUE) {
r = requested.addAndGet(-e);
}
upstream.request(e);
e = 0L;
}
}
}
}
可以看到初始化了 SimpleQueue ,之后 v = q.poll(),阻塞等待。这里如果数据发射在
SubscribeOnSubscriber 的 run
public void run() {
lazySet(Thread.currentThread());
Publisher<T> src = source;
source = null;
src.subscribe(this);
}
将 FlowableSubscribeOn 初始化时候传进的 Flowable.fromCallable 赋值给 src,之后订阅我们的事件,所以我们的事件触发在IO线程。经过 FlowableFromCallable 的 callable.call(),依次传递,之后调用 SubscribeOnSubscriber 的 onNext,如下,这里 downstream 自然是 ObserveOnSubscriber 。
@Override
public void onNext(T t) {
downstream.onNext(t);
}
ObserveOnSubscriber 中,它的 onComplete 方法如下
@Override
public final void onNext(T t) {
//判断
trySchedule();
}
trySchedule 方法又将启动 SINGLE 线程,和之前 ObserveOnSubscriber 的 run 一直。这次可以取得数据,并执行 a.onNext(v),这里的 a 即 LambdaSubscriber,即我们自己的 Consumer。
如果我们创建多个 subscribeOn,那么数据发射会在哪个线程?自然,是最上层的线程了。
而创建多个 observeOn 则不同,每次都需要发送到 observeOn 创建的线程中。
最后看下 rxandroid 中的 AndroidSchedulers
public static Scheduler mainThread() {
return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
}
private static final class MainHolder {
static final Scheduler DEFAULT
= new HandlerScheduler(new Handler(Looper.getMainLooper()), false);
}
private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
new Callable<Scheduler>() {
@Override public Scheduler call() throws Exception {
return MainHolder.DEFAULT;
}
});
它则创建 HandlerScheduler 对象,内部创建 HandlerWorker,schedule 方法则是将 runnable 交给主线程的 handler 处理,附上代码
public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
/判断
ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);
Message message = Message.obtain(handler, scheduled);
message.obj = this; // Used as token for batch disposal of this worker's runnables.
if (async) {
message.setAsynchronous(true);
}
handler.sendMessageDelayed(message, unit.toMillis(delay));
//
return scheduled;
}