Rxjava源码(三)-----线程控制Scheduler

来源:互联网 发布:servo guide软件下载 编辑:程序博客网 时间:2024/05/17 07:05

又是一个令人激动的东西,真不想说废话了,开始神奇之旅吧(原谅我这么土鳖,就是觉得很神奇,不看不知道,一看吓一跳啊)

灵活的变换已经让我们眼花缭乱了,线程的自由控制更是让RxJava的牛叉之气更上一层楼。

前边我们已经知道了可以利用subscribeOn()结合observeOn()来实现线程控制,让事件的产生和消费发生在不同的线程,map() flatMap()等方法都可以多次变换,那线程切换能不能多次呢?

答案当然是能啦,因为observeOn指定的是Subscriber的线程,而这个Subscriber并不一定是(此处可较真,理解为 不是)subscribe()参数中的Subscriber,而是observeOn()执行时的当前observable所对应的Subscriber,即它的直接下级Subscriber,换句话说,observeOn()指定的是它之后的操作所在的线程,因此,如果有多次切换线程的需求,只要在每个想要切换线程的位置调用一次observeOn()即可。

Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定    .subscribeOn(Schedulers.io())    .observeOn(Schedulers.newThread())    .map(mapOperator) // 新线程,由 observeOn() 指定    .observeOn(Schedulers.io())    .map(mapOperator2) // IO 线程,由 observeOn() 指定    .observeOn(AndroidSchedulers.mainThread)     .subscribe(subscriber);  // Android 主线程,由 observeOn() 指定
不同于observeOn(),subscribeOn()的位置放哪里都可以,但是它只能调用一次,那如果非要调用多次呢,这个问题我们从线程控制的原理开始说起吧

Scheduler原理:

subscribeOn()和observeOn()的内部实现,也是用了lift()方法,

先看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是由just方法创建的,我们看看他的走向:

public Observable<T> scalarScheduleOn(Scheduler scheduler) {        if (scheduler instanceof EventLoopsScheduler) {            EventLoopsScheduler es = (EventLoopsScheduler) scheduler;            return create(new DirectScheduledEmission<T>(es, t));        }        return create(new NormalScheduledEmission<T>(scheduler, t));    }
这里可以看到根据Scheduler的类型又分为两种情况,不过都是创建一个新的Observable<T>对象。那么不同的就是两个OnSubscribe<T>对象了,一个是DirectScheduledEmission,另一个是NormalScheduleEmission。
    /** Optimized observeOn for scalar value observed on the EventLoopsScheduler. */    static final class DirectScheduledEmission<T> implements OnSubscribe<T> {        private final EventLoopsScheduler es;        private final T value;        DirectScheduledEmission(EventLoopsScheduler es, T value) {            this.es = es;            this.value = value;        }        @Override        public void call(final Subscriber<? super T> child) {            child.add(es.scheduleDirect(new ScalarSynchronousAction<T>(child, value)));        }    }
   /** Emits a scalar value on a general scheduler. */    static final class NormalScheduledEmission<T> implements OnSubscribe<T> {        private final Scheduler scheduler;        private final T value;        NormalScheduledEmission(Scheduler scheduler, T value) {            this.scheduler = scheduler;            this.value = value;        }                @Override        public void call(final Subscriber<? super T> subscriber) {            Worker worker = scheduler.createWorker();            subscriber.add(worker);            worker.schedule(new ScalarSynchronousAction<T>(subscriber, value));        }    }
/** Action that emits a single value when called. */    static final class ScalarSynchronousAction<T> implements Action0 {        private final Subscriber<? super T> subscriber;        private final T value;        private ScalarSynchronousAction(Subscriber<? super T> subscriber,                T value) {            this.subscriber = subscriber;            this.value = value;        }        @Override        public void call() {            try {                subscriber.onNext(value);            } catch (Throwable t) {                subscriber.onError(t);                return;            }            subscriber.onCompleted();        }    }

。。。。。。。再来看一下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));    }

这里我不想先分析第一种情况了,先来看第二种情况吧:

nest()函数干了啥:

public final Observable<Observable<T>> nest() {        return just(this);    }

so easy,调用了just方法,但是请注意,这里的this,把最原始的这个Observable当做参数传入了,

public final static <T> Observable<T> just(final T value) {        return ScalarSynchronousObservable.create(value);    }
还是来复习看一下这个ScalarSynchronousObservable吧

public final class ScalarSynchronousObservable<T> extends Observable<T> {    public static final <T> ScalarSynchronousObservable<T> create(T t) {        return new ScalarSynchronousObservable<T>(t);    }    private final T t;    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;    }          // 暂且省略无关代码

看到这个ScalarSynchronousObservable对象,我们此时需要记住的是:原始Observable被当做一个属性保存在ScalarSynchronousObservable对象中,看图:


以上是nest()函数调用以后发生的事情,接着开始看lift()函数:先复习一下原来我们分析的lift原理图:


lift方法会创建一个Observable<T>对象,该对象的内部有一个OnSubscribe<T>对象,它的call方法会调用OperatorSubscribeOn.call方法得到一个Subscriber<Observable<T>>对象,并在调用上面的Observable<Observable<T>>.OnSubscribe<Observable<T>>.call方法时传递进去。那么来看下OperatorSubscribeOn.call是如何将一个Subscribe<T>转换成Subscriber<Observable<T>>对象的。

public class OperatorSubscribeOn<T> implements Operator<T, Observable<T>> {    private final Scheduler scheduler;    public OperatorSubscribeOn(Scheduler scheduler) {        this.scheduler = scheduler;    }    @Override    public 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方法里面实例化了一个Subscriber<T>对象并返回。该Subscriber<T>的onNext方法中会调用Scheduler.schedule将一个Action0加入线程池里执行,该Action0的call方法会触发原始Observable<T>的unsafeSubscribe方法,然后会触发原始OnSubscribe<T>.call方法,也就是说原始OnSubscribe<T>.call方法是在切换后的线程中执行。如图 








0 0
原创粉丝点击