RxJava之Schedulers详解
来源:互联网 发布:文艺知乎 编辑:程序博客网 时间:2024/05/22 06:45
本来是想说说RxJava之转换器的,但是发现,如果不来讲讲Rx的Schedulers,好像总感觉少了点什么。因为RxJava让我们用的最爽的地方,莫过于这一块了。我们可以随意的进行线程切换,是那么的简洁优美,尤其是配合RxAndroid之后,我们可以随意的进行子线程和UI线程的切换。同时,我们也可以自己来定义Rx之线程池的实现,合理分配应用的线程,本来就是应用开发的重中之重。本节以模拟两个线程池为例,来演示并讲解Schedulers。
首先我们自己构造一个Observable:
public static Observable<Integer> computeSum(final int n){ return Observable.create(new Observable.OnSubscribe<Integer>() { @Override public void call(Subscriber<? super Integer> subscriber) { try{ int sum = 0; for (int i = 0; i <= n; i ++){ sum += i; } System.out.println("computeSum on thread = " + Thread.currentThread()); subscriber.onNext(sum); }catch (Throwable e){ subscriber.onError(e); }finally { subscriber.onCompleted(); } } });}
在这个Observable里面,我们会打印出当前所在的线程。然后,我们构造出两个不同线程池的Schedulers,并且让这个Observable执行在不同的线程上:
Scheduler observeOnSchedule = Schedulers.from(Executors.newSingleThreadExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r, "observeOnThread"); } })); Scheduler subscribeOnSchedule = Schedulers.from(Executors.newFixedThreadPool(3, new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r, "mapSchedule"); } })); computeSum(1000).subscribeOn(subscribeOnSchedule).observeOn(observeOnSchedule).subscribe(new Action1<Integer>() { @Override public void call(Integer integer) { System.out.println("observeOn=======================" + Thread.currentThread()); } });
运行结果如下:
computeSum on thread = Thread[subscribeOnThread,5,main]
observeOn=======================Thread[observeOnThread,5,main]
由此可见这个Observable执行在不同的线程池上。subscribeOn定义的为Observable中call执行所在的线程,而observeOn则定义的为subscribe执行所在的线程,为什么会如此神奇呢?我们来看看它是如何实现的。接下来一步步揭开来
subscribeOn运行流程
public final Observable<T> subscribeOn(Scheduler scheduler) { if (this instanceof ScalarSynchronousObservable) { return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler); } return nest().lift(new OperatorSubscribeOn<T>(scheduler));}
方法很简单,首先判断当前observable是不是ScalarSynchronousObservable类型的,如果是则会直接执行scalarScheduleOn方法,如果不是,则会通过nest()方法创建一个ScalarSynchronousObservable并把当前的Observable包装进去,并且lift一个OperatorSubscribeOn进去。这一块说起来挺简单,内部源码看起来就有点晦涩了。但是溯根追源,我们来看下observable经过这一些列之后的变化,就会清晰很多了。
看图可以知道,这个过程中,最终生成了三个Observable,而当执行subscribe方法的时候,则一次执行的为最后生成的Observable的call方法也就是如下代码:
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) { return new Observable<R>(new OnSubscribe<R>() { @Override public void call(Subscriber<? super R> o) { try { Subscriber<? super T> st = hook.onLift(operator).call(o); try { // new Subscriber created and being subscribed with so 'onStart' it st.onStart(); onSubscribe.call(st); } catch (Throwable e) { // localized capture of errors rather than it skipping all operators // and ending up in the try/catch of the subscribe method which then // prevents onErrorResumeNext and other similar approaches to error handling Exceptions.throwIfFatal(e); st.onError(e); } } catch (Throwable e) { Exceptions.throwIfFatal(e); // if the lift function failed all we can do is pass the error to the final Subscriber // as we don't have the operator available to us o.onError(e); } } });}
其中Subscriber <? super T> st = hook.onLift(operator).call(o);
(暂且称之为sub1)返回的为OperatorSubscribeOn执行call方法执行的结果,这里稍后的再说。继续往下走,最终会发现,调用的为ScalarSynchronousObservable的onSubscribe的call方法,传递参数为sub1。这里的方法很简单:
protected ScalarSynchronousObservable(final T t) { super(new OnSubscribe<T>() { @Override public void call(Subscriber<? super T> s) { /* * We don't check isUnsubscribed as it is a significant performance impact in the fast-path use cases. * See PerfBaseline tests and https://github.com/ReactiveX/RxJava/issues/1383 for more information. * The assumption here is that when asking for a single item we should emit it and not concern ourselves with * being unsubscribed already. If the Subscriber unsubscribes at 0, they shouldn't have subscribed, or it will * filter it out (such as take(0)). This prevents us from paying the price on every subscription. */ s.onNext(t); s.onCompleted(); } }); this.t = t;}
只是简单的执行了sub1的onNext(t)方法和onComplete方法。请注意这里,t为我们最原始的observable也就是我们的compute的observable。
@Overridepublic Subscriber<? super Observable<T>> call(final Subscriber<? super T> subscriber) { final Worker inner = scheduler.createWorker(); subscriber.add(inner); return new Subscriber<Observable<T>>(subscriber) { @Override public void onCompleted() { // ignore because this is a nested Observable and we expect only 1 Observable<T> emitted to onNext } @Override public void onError(Throwable e) { subscriber.onError(e); } @Override public void onNext(final Observable<T> o) { inner.schedule(new Action0() { @Override public void call() { final Thread t = Thread.currentThread(); o.unsafeSubscribe(new Subscriber<T>(subscriber) { @Override public void onCompleted() { subscriber.onCompleted(); } @Override public void onError(Throwable e) { subscriber.onError(e); } @Override public void onNext(T t) { subscriber.onNext(t); } @Override public void setProducer(final Producer producer) { subscriber.setProducer(new Producer() { @Override public void request(final long n) { if (Thread.currentThread() == t) { // don't schedule if we're already on the thread (primarily for first setProducer call) // see unit test 'testSetProducerSynchronousRequest' for more context on this producer.request(n); } else { inner.schedule(new Action0() { @Override public void call() { producer.request(n); } }); } } }); } }); } }); } };}
这个是OperatorSubscribeOn的call方法,看上面的讲解我们可以明白,最终调用的sub1的onNext(t)方法就是这里的onNext方法,传递的Observable就是最初是的observable。而这里的inner创建是由ExecutorScheduler类创建的(具体看 Schedulers类就明白),所以inner也就是ExecutorSchedulerWorker的实例,最终调用的是ExecutorSchedulerWorker类的schedule方法,如下:
@Override public Subscription schedule(Action0 action) { if (isUnsubscribed()) { return Subscriptions.unsubscribed(); } ScheduledAction ea = new ScheduledAction(action, tasks); tasks.add(ea); queue.offer(ea); if (wip.getAndIncrement() == 0) { try { // note that since we schedule the emission of potentially multiple tasks // there is no clear way to cancel this schedule from individual tasks // so even if executor is an ExecutorService, we can't associate the future // returned by submit() with any particular ScheduledAction executor.execute(this); } catch (RejectedExecutionException t) { // cleanup if rejected tasks.remove(ea); wip.decrementAndGet(); // report the error to the plugin RxJavaPlugins.getInstance().getErrorHandler().handleError(t); // throw it to the caller throw t; } } return ea; }
此处代码就是把ScheduledAction放进queue里面,然后不停的从queue里面取出ScheduledAction并执行run方法,而run方法里面就是上一级里面onNext里面的call方法,具体可以去看代码,里面就是执行observable(最初的observable)的call方法等等。。如此,一系列observable的操作都是放在了我们最初创建的线程池里了。
observeOn运行流程
上面分析了如何让Observable的代码运行在其它线程里,接下来分析下,如何让Subscriber运行在其他线程里。这里比较简单,因为Subscriber的代码逻辑要比上面的简单。因为Observable是经过层层包装以及变幻,最终生成的Observable已经不是最初的Observable,而Subscriber虽然也有很多个,但是最终值得我们关注的却只有最后一个。接下来看具体代码逻辑,首先是observeOn方法:
public final Observable<T> observeOn(Scheduler scheduler) { if (this instanceof ScalarSynchronousObservable) { return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler); } return lift(new OperatorObserveOn<T>(scheduler));}
这里比较简单,Observable并没有经过什么变换,而是直接lift一个OperatorObserveOn,产生的Observable为(本次不测试subscribeOn):
由此可见,最终执行的为OperatorObserveOn的onNext方法。。如下:
@Override public void onNext(final T t) { if (isUnsubscribed()) { return; } if (!queue.offer(on.next(t))) { onError(new MissingBackpressureException()); return; } schedule(); }
把Observable处理过的对象放到queue里面,这里的queue可能会存多个t(当observable执行的很快而且Subscriber并没有unsubscribe的时候,如果Subscriber的onNext方法执行较慢的时候)。而schedule方法就是在当前指定的Scheduler所在在线程上面执行pollQueue:
final Action0 action = new Action0() { @Override public void call() { pollQueue(); } }; protected void schedule() { if (counter.getAndIncrement() == 0) { recursiveScheduler.schedule(action); } }
schedule里面只是判断下当前是否在线程里面执行onNext方法。来看pollQueue:
void pollQueue() { int emitted = 0; final AtomicLong localRequested = this.requested; final AtomicLong localCounter = this.counter; do { localCounter.set(1); long produced = 0; long r = localRequested.get(); for (;;) { if (child.isUnsubscribed()) return; Throwable error; if (finished) { if ((error = this.error) != null) { // errors shortcut the queue so // release the elements in the queue for gc queue.clear(); child.onError(error); return; } else if (queue.isEmpty()) { child.onCompleted(); return; } } if (r > 0) { Object o = queue.poll(); if (o != null) { child.onNext(on.getValue(o)); r--; emitted++; produced++; } else { break; } } else { break; } } if (produced > 0 && localRequested.get() != Long.MAX_VALUE) { localRequested.addAndGet(-produced); } } while (localCounter.decrementAndGet() > 0); if (emitted > 0) { request(emitted); } }
代码虽然很多,其实多数只是执行一些逻辑判断,其主要的含义就是,设置counter为1,然后不停的从queue里面取数据,然后调用child的onNext方法(child为最原始我们定义的Subcriber),直到把queue里面的数据取完之后,方法结束。
综上所述,可以看出,subscribeOn所执行的操作是用Observable来包装原来的Observable,而observeOn所执行的操作是用一个ObserveOnSubscriber来包装我们定义的Subscriber。RxJava原来难懂的地方也在这里,对象层层包装,然后像个钩子一样层层回调回来,就形成了流水线一样的过程。
杏树林研发 徐英建
- RxJava之Schedulers详解
- RxJava之调度器(Schedulers)
- rxJava Schedulers Use Cases
- Rxjava Schedulers 使用
- Rxjava(2.Schedulers调度器)
- 我的android多线程编程之路(2)之RxJava Schedulers源码分析
- RxJava:Schedulers选择 newThread vs io
- RxJava之入门详解
- Android之RxJava 详解
- RxJava开发精要7 - Schedulers-解决Android主线程问题
- 【RxJava Demo分析】(二)Schedulers线程调度器
- Android 开发之RxJava 详解
- RxJava之深入浅出进阶详解
- RxJava 之四—— Lift()详解
- RxJava 之二—— Lift()详解
- menuconfig详解(4)——IO Schedulers
- RxJava 学习记(三) —— 1.x 线程调度器Schedulers
- RxJava 详解
- 初级还是高级开发者,到底区别在哪里?
- 这个控件找不到的问题.报错瞎报..
- Linux下C++调用Java简单实例(jni)
- java生成指定范围的随机数
- Java 简单加法器的实现
- RxJava之Schedulers详解
- 升级10.11后Xcode的CocoaPods插件报错
- wifidog接口文档
- 第三章:WORKING WITH TEXT DATA
- mysql-删除重复的数据,重复的数据只保留一条
- 爱因斯坦思考题(多维穷举)
- 学习理论-贝叶斯统计和正则化
- 转载_架构师重构代码的12条军规
- 简单打开.swf文件