RxJava线程调度源码解析

转载请保留原文链接:http://blog.csdn.net/u010593680/article/details/53911475

先看一个简单的使用,下例子在io线程中模拟获取了图片,并在主线程(Android)中输出了该图片:

    Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {//getImage运行在subscribeOn设置的线程
            String img = getImage();//获取图片,io线程
            if (img != null) {
                subscriber.onNext(img);
            } else {
                subscriber.onError(new IllegalStateException());
            }
        }
    })
            .subscribeOn(Schedulers.io())//设置上面操作运行在io线程
            .observeOn(AndroidSchedulers.mainThread())//设置下方操作运行在主线程
            .subscribe(new Action1<String>() {
                @Override
                public void call(String s) {//主线程中运行
                    Log.e(TAG, "图片:" + s);
                }
            });

接下来将对observeOn和subscribeOn两个方法的实现方式作解析。

observeOn(指定线程):改变下游操作运行的线程

public final Observable<T> observeOn(Scheduler scheduler) {
    return observeOn(scheduler, RxRingBuffer.SIZE);
}

//最后会调用该方法

public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
    if (this instanceof ScalarSynchronousObservable) {
        return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler);
    }
    return lift(new OperatorObserveOn<T>(scheduler, delayError, bufferSize));
}

使用了Lift生成一个新的Observable,并将OperatorObserveOn作为新Observable的OnSubscribe,不清楚Lift可查看我的上一篇blog,简要介绍Lift的操作就是能将下游的subscriber的传输给OperatorObserveOn,这也是observeOn方法能改变下游操作的线程的原因。
OperatorObserveOn的call方法将下游的subscriber包装成ObserveOnSubscriber:

@Override
public Subscriber<? super T> call(Subscriber<? super T> child) {
    if (scheduler instanceof ImmediateScheduler) {
        // avoid overhead, execute directly
        return child;
    } else if (scheduler instanceof TrampolineScheduler) {
        // avoid overhead, execute directly
        return child;
    } else {
        ObserveOnSubscriber<T> parent = new ObserveOnSubscriber<T>(scheduler, child, delayError, bufferSize);//包装并返回新的subscriber
        parent.init();
        return parent;
    }
}

ObserveOnSubscriber简化代码:

/** Observe through individual queue per observer. */
private static final class ObserveOnSubscriber<T> extends Subscriber<T> implements Action0 {

    public ObserveOnSubscriber(Scheduler scheduler, Subscriber<? super T> child, boolean delayError, int bufferSize) {
        this.child = child;
        this.recursiveScheduler = scheduler.createWorker();
       //...
    }

    void init() {
        // don't want this code in the constructor because `this` can escape through the 
        // setProducer call
        Subscriber<? super T> localChild = child;

        localChild.setProducer(new Producer() {//设置生产者

            @Override
            public void request(long n) {
                if (n > 0L) {
                    BackpressureUtils.getAndAddRequest(requested, n);
                    schedule();
                }
            }

        });
        localChild.add(recursiveScheduler);
        localChild.add(this);
    }

    @Override
    public void onNext(final T t) {
        if (isUnsubscribed() || finished) {
            return;
        }
        //...
        schedule();//切换线程
    }

    @Override
    public void onCompleted() {
        if (isUnsubscribed() || finished) {
            return;
        }
        finished = true;
        schedule();//切换线程
    }

    @Override
    public void onError(final Throwable e) {
        if (isUnsubscribed() || finished) {
            RxJavaPlugins.getInstance().getErrorHandler().handleError(e);
            return;
        }
        error = e;
        finished = true;
        schedule();//切换线程
    }

    protected void schedule() {
        if (counter.getAndIncrement() == 0) {
            recursiveScheduler.schedule(this);//在其他线程调用call方法
        }
    }

    // only execute this from schedule()
    @Override
    public void call() {//schedule()调用后,在其他线程调用
        //...
                if (checkTerminated(done, empty, localChild, q)) {//检查是否已完成了,完成了调用onCompleted,onError方法
                    return;
                }

                localChild.onNext(localOn.getValue(v));
                /...
        }
    }

    boolean checkTerminated(boolean done, boolean isEmpty, Subscriber<? super T> a, Queue<Object> q) {
    //该方法里会判断状态,可能调用onCompleted,onError等方法
        if (a.isUnsubscribed()) {
            q.clear();
            return true;
        }

        if (done) {
            if (delayError) {
                if (isEmpty) {
                    Throwable e = error;
                    try {
                        if (e != null) {
                            a.onError(e);
                        } else {
                            a.onCompleted();
                        }
                    } finally {
                        recursiveScheduler.unsubscribe();
                    }
                }
            } else {
                Throwable e = error;
                if (e != null) {
                    q.clear();
                    try {
                        a.onError(e);
                    } finally {
                        recursiveScheduler.unsubscribe();
                    }
                    return true;
                } else
                if (isEmpty) {
                    try {
                        a.onCompleted();
                    } finally {
                        recursiveScheduler.unsubscribe();
                    }
                    return true;
                }
            }

        }

        return false;
    }
}

由以上代码可以知道:
* observeOn以后会生成新的subscriber
* observeOn切换线程的时机是生产者生产出产品后,调用subscriber的onNext,onCompleted,onError方法时,此时会先切换线程,再调用onNext,onCompleted,onError
* observeOn不影响上游操作执行的线程
* observeOn可以切换多次下游操作的执行线程,因为lift可以多次包装生成新的Observable

subscribeOn(指定线程) :改变上游操作的运行线程

先看下代码:

public final Observable<T> subscribeOn(Scheduler scheduler) {
    if (this instanceof ScalarSynchronousObservable) {
        return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler);
    }
    return create(new OperatorSubscribeOn<T>(this, scheduler));//和observeOn不同的是并没使用lift,只对上游操作做了包装,因为subscribeOn改变的是上游操作
}

继续看下OperatorSubscribeOn:

public final class OperatorSubscribeOn implements OnSubscribe {

final Scheduler scheduler;
final Observable<T> source;

public OperatorSubscribeOn(Observable<T> source, Scheduler scheduler) {
    this.scheduler = scheduler;//设置的线程调度器
    this.source = source;//上游的observable
}

@Override
public void call(final Subscriber<? super T> subscriber) {
    final Worker inner = scheduler.createWorker();
    subscriber.add(inner);

    inner.schedule(new Action0() {//在用户设置的线程里进行call操作
        @Override
        public void call() {//用户设置的线程里运行
            final Thread t = Thread.currentThread();

            Subscriber<T> s = new Subscriber<T>(subscriber) {//复制一个subscriber,只是简单包装,没做额外的操作
                @Override
                public void onNext(T t) {
                    subscriber.onNext(t);
                }

                @Override
                public void onError(Throwable e) {
                    try {
                        subscriber.onError(e);
                    } finally {
                        inner.unsubscribe();
                    }
                }

                @Override
                public void onCompleted() {
                    try {
                        subscriber.onCompleted();
                    } finally {
                        inner.unsubscribe();
                    }
                }

                @Override
                public void setProducer(final Producer p) {
                    subscriber.setProducer(new Producer() {//线程切换的关键在这里
                        @Override
                        public void request(final long n) {
                            if (t == Thread.currentThread()) {//如果和用户设置的线程相同
                                p.request(n);
                            } else {
                                inner.schedule(new Action0() {//切换线程
                                    @Override
                                    public void call() {//在用户设置的线程里运行
                                        p.request(n);//请求生产者生产出来的产品,即:生产者调用onNext等操作
                                    }
                                });
                            }
                        }
                    });
                }
            };

            source.unsafeSubscribe(s);
        }
    });
}
subscribeOn操作总结
  1. subscribeOn也是对subscriber作了包装
  2. subscribeOn会改变上游和下游的运行线程,(但如果调用了observeOn还是能切换下游线程,因为observeOn使用lift对下游操作进行了包装,所以即使subscribeOn改变了线程,observeOn的包装也会再次切换线程)
  3. 多个subscribeOn只有最上游的一个起作用

上面的第2点,举个例子,下面的程序只使用了一个subscribeOn也就是说上下游代码都执行在Schedulers.io()设置的线程里,所以下方设置图片就会崩溃:

    Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {//getImage运行在subscribeOn设置的线程
            String img = getImage();
            if (img != null) {
                subscriber.onNext(img);
            } else {
                subscriber.onError(new IllegalStateException());
            }
        }
    })
            .subscribeOn(Schedulers.io()) //subscribeOn 1
            .subscribe(new Action1<String>() {
                @Override
                public void call(String s) {//Schedulers.io()
                    Log.e(TAG, "设置图片:" + s);
                    mIvDown.setImageResource(R.drawable.power_close);
                }
            });

上面的第3点不太好理解,举个例子:

    Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {//getImage运行在subscribeOn设置的线程
            String img = getImage();
            if (img != null) {
                subscriber.onNext(img);
            } else {
                subscriber.onError(new IllegalStateException());
            }
        }
    })
            .subscribeOn(Schedulers.io()) //subscribeOn 1
            .subscribeOn(AndroidSchedulers.mainThread()) //subscribeOn 2
            .subscribe(new Action1<String>() {
                @Override
                public void call(String s) {//subscribeOn 1线程,即Schedulers.io()
                    Log.e(TAG, "设置图片:" + s);
                    mIvDown.setImageResource(R.drawable.power_close);
                    //在非主线程操作,所以会崩溃
                }
            });

虽然subscribeOn2确实切换了线程,但又给subscribeOn1切换了线程,之后在运行subscriber的onNext等方法
虽然subscribeOn2确实切换了线程2,但又给subscribeOn1切换到了线程1,之后再运行subscriber的onNext等方法

各个线程调度的内部实现:

  • Schedulers.io()将操作放在线程池里运行,其schedule()方法立刻将操作调用Executor.submit方法,并且保存返回值future以便日后取消执行
  • AndroidSchedulers.mainThread()使用Handler(MainLooper)方式在主线程调用操作

原文:http://blog.csdn.net/u010593680/article/details/53911475
部分内容可参考上一篇博客,如有问题欢迎指正~

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RxJava中的flatMap操作符是一个非常常用的操作符,它可以将一个Observable发射的事件序列转换成多个Observables,然后将这些Observables发射的事件序列合并后再发射出去。 下面是flatMap操作符的源码解析: ```java public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) { ObjectHelper.requireNonNull(mapper, "mapper is null"); return RxJavaPlugins.onAssembly(new ObservableFlatMap<>(this, mapper, false, Integer.MAX_VALUE, bufferSize())); } ``` 可以看到,flatMap操作符的实现是通过创建一个ObservableFlatMap对象来完成的。其中,mapper参数表示将原始Observable发射的事件转换成的新Observable,它是一个Function类型的参数,即接受一个T类型的参数并返回一个ObservableSource类型的结果。 ObservableFlatMap的构造函数如下所示: ```java ObservableFlatMap(ObservableSource<T> source, Function<? super T, ? extends ObservableSource<? extends R>> mapper, boolean delayErrors, int maxConcurrency, int bufferSize) { this.source = source; this.mapper = mapper; this.delayErrors = delayErrors; this.maxConcurrency = maxConcurrency; this.bufferSize = bufferSize; } ``` ObservableFlatMap的核心实现是在subscribeActual方法中完成的: ```java @Override public void subscribeActual(Observer<? super R> observer) { if (ObservableScalarXMap.tryScalarXMapSubscribe(source, observer, mapper)) { return; } source.subscribe(new FlatMapObserver<>(observer, mapper, delayErrors, maxConcurrency, bufferSize)); } ``` 在subscribeActual方法中,首先判断源Observable是否可以直接转换为ObservableScalarXMap,如果可以的话直接进行转换,否则创建一个FlatMapObserver对象并进行订阅。 FlatMapObserver是flatMap的核心实现类,它实现了Observer接口,并且在接收到源Observable发射的事件时,会先将事件转换成新的Observable,然后将新Observable的发射事件序列合并到一个新的Observable中,最后再将新的Observable发射出去。 ```java static final class FlatMapObserver<T, R> extends AtomicInteger implements Observer<T>, Disposable { // ... @Override public void onNext(T t) { ObservableSource<? extends R> o; try { o = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper returned a null ObservableSource"); } catch (Throwable e) { Exceptions.throwIfFatal(e); upstream.dispose(); onError(e); return; } if (cancelled) { return; } if (maxConcurrency != Integer.MAX_VALUE) { synchronized (this) { if (wip == maxConcurrency) { queue.offer(t); return; } wip++; } } o.subscribe(new InnerObserver(inner, delayErrors, this)); } // ... } ``` 在FlatMapObserver的onNext方法中,首先调用mapper将源Observable发射的事件转换成新的Observable,并进行非空检查。然后判断当前的并发度是否达到了最大值,如果达到了最大值,就将源Observable发射的事件放到队列中。否则,就将并发度加1,并订阅新Observable。 InnerObserver是FlatMapObserver的内部类,它实现了Observer接口,并在接收到来自新Observable的发射事件序列时,将它们合并到一个新的Observable中,并将新的Observable发射出去。 ```java static final class InnerObserver<R> implements Observer<R> { // ... @Override public void onNext(R t) { if (done) { return; } inner.onNext(t); } // ... } ``` 当所有的新Observable都完成后,FlatMapObserver会调用onComplete方法通知观察者。如果发生了异常,FlatMapObserver会调用onError方法通知观察者。同时,FlatMapObserver还实现了Disposable接口,可以通过dispose方法取消订阅。 综上所述,flatMap操作符的实现是比较复杂的,它通过创建ObservableFlatMap对象,并在subscribeActual方法中创建FlatMapObserver对象来完成转换操作。在FlatMapObserver中,它还需要实现对新Observable的订阅以及将新Observable发射的事件合并到一个新的Observable中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值