RxJava源码解析05-线程切换

RxJava源码解析05-线程切换

这篇文章我们来分析一下RxJava线程的切换。

Observable.just("123")
    .subscribeOn(Schedulers.io())
    .observeOn(Schedulers.newThread())
    .subscribe(new Subscriber<String>() {
        @Override
        public void onCompleted() {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onNext(String s) {

        }
    });   

subscribeOn

observaOn作用于该操作符之后直到出现新的observeOn操作符,在Observer.onNext、onCompleted、onError的时候进行切换。subscribeOn可以进行多次切换。

subscribeOn

subscribeOn作用于该操作符之前的Observable的创建操作符以及doOnSubscribe操作符,subscribeOn有多个时,只有第一个有效(除doSubscriber外,doSubscribe会在OnSubscribe.call前调用)

在Onsubscribe.call()时进行切换  

subscribeOn源码解析

public final Observable<T> subscribeOn(Scheduler scheduler, boolean requestOn) {
    if (this instanceof ScalarSynchronousObservable) {
        return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler);
    }
    return unsafeCreate(new OperatorSubscribeOn<T>(this, scheduler, requestOn));
}

来看OperatorSubscribeOn

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

    SubscribeOnSubscriber<T> parent = new SubscribeOnSubscriber<T>(subscriber, requestOn, inner, source);
    subscriber.add(parent);
    subscriber.add(inner);

    inner.schedule(parent);
}  

这里会调用scheduler.createWorker();创建Worker,并调用schedule。而这个scheduler是构造方法传参进来的,这是调用subscribeOn()传入的参数。

来看下Schedulers.newThread(),跟踪源码会发现,是NewThreadScheduler类

public final class NewThreadScheduler extends Scheduler {
    private final ThreadFactory threadFactory;

    public NewThreadScheduler(ThreadFactory threadFactory) {
        this.threadFactory = threadFactory;
    }

    @Override
    public Worker createWorker() {
        return new NewThreadWorker(threadFactory);
    }
}  

主要来看NewThreadWorker

public NewThreadWorker(ThreadFactory threadFactory) {
    ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, threadFactory);

    boolean cancelSupported = tryEnableCancelPolicy(exec);
    if (!cancelSupported && exec instanceof ScheduledThreadPoolExecutor) {
        registerExecutor((ScheduledThreadPoolExecutor)exec);
    }
    executor = exec;
}  

可以看到这里创建了线程池,再来看schedule方法

@Override
public Subscription schedule(final Action0 action, long delayTime, TimeUnit unit) {
    if (isUnsubscribed) {
        return Subscriptions.unsubscribed();
    }
    return scheduleActual(action, delayTime, unit);
}  

public ScheduledAction scheduleActual(final Action0 action, long delayTime, TimeUnit unit) {
    Action0 decoratedAction = RxJavaHooks.onScheduledAction(action);
    ScheduledAction run = new ScheduledAction(decoratedAction);
    Future<?> f;
    if (delayTime <= 0) {
        f = executor.submit(run);
    } else {
        f = executor.schedule(run, delayTime, unit);
    }
    run.add(f);

    return run;
}  

可以看到这里调用了executor.submit(),action是之前OperatorSubscribeOn.schedule传入的parent对象,这是个Action0的子类,最终会调用parent.call。parent是SubscribeOnSubscriber

@Override
public void call() {
    //...
    src.unsafeSubscribe(this); //src是subscribe
}  

从而onNext、onCompleted、onError的时候,就已经在切换后的线程中执行了,从而实现了线程的切换。

@Override
public void onNext(T t) {
    actual.onNext(t);
}

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

@Override
public void onCompleted() {
    try {
        actual.onCompleted();
    } finally {
        worker.unsubscribe();
    }
}  

observeOn 源码分析

经过一些方法,会调用Observer#observeOn()

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

lift方法会将传入的T转换为R,这里的OperatorObserveOn继承自Operator

总结

RxJava的线程切换其实就是根据Schedulers生成的Scheduler,最终调用相应的线程池来进行线程切换。

如果是或AndroidSchedulers.mainThread,则会使用Handler来切换到主线程。

class LooperScheduler extends Scheduler {
    //...       

    @Override
    public Subscription schedule(Action0 action, long delayTime, TimeUnit unit) {
        if (unsubscribed) {
            return Subscriptions.unsubscribed();
        }

        action = hook.onSchedule(action);

        ScheduledAction scheduledAction = new ScheduledAction(action, handler);

        Message message = Message.obtain(handler, scheduledAction);
        message.obj = this; // Used as token for unsubscription operation.

        handler.sendMessageDelayed(message, unit.toMillis(delayTime));

        if (unsubscribed) {
            handler.removeCallbacks(scheduledAction);
            return Subscriptions.unsubscribed();
        }

        return scheduledAction;
    }

    //...
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

氦客

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值