RxJava2ソースコード分析ノート(3)スレッドの切り替え

RxJava2ソースコード分析ノート(1)

RxJava2ソースコード分析ノート(2)

ついにスレッド切り替えになりました

まず、ねじ山を切る方法の簡単なフローチャートを見てください

注:上記の青いメインプロセスでは、subscribeOn(Schedulers.io())、observeOn(AndroidSchedulers.mainThread())

        ただし、subscribeOnとobserveOnはメインスレッドまたは子スレッドに渡すことができます

        これは、RxJavaスレッドを柔軟に元に戻すための鍵です。

================================================== ==================

最初に見てください

subscribeOn(Schedulers.io())

これは2つの部分に分かれています

| ------ subscribeOn()はRunnable {run {  source.subscribe(parent);  }を作成し、コアはsource.subscribe(parent)であり、Schedulers.io()によって作成されたスケジューラーに渡します。コール。

| ------ Schedulers.io()は、新しいスレッドを作成して使用するようにスケジュールするために使用されるスケジューラーを返します。

 

次に、subscribeOn()がどのように実装されているかを見てみましょう(構造はmapなどのデータ変換操作と同じです)

/**
 *    subscribeOn  核心是new ObservableSubscribeOn<T>(this, scheduler)
 */   
 @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.CUSTOM)
    public final Observable<T> subscribeOn(Scheduler scheduler) {
        ObjectHelper.requireNonNull(scheduler, "scheduler is null");
        
        return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
    }

ObservableSubscribeOn源码 ↓ 
public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    final Scheduler scheduler;

    public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
        super(source);
        this.scheduler = scheduler;
    }

    @Override
    public void subscribeActual(final Observer<? super T> s) {
        final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);

        s.onSubscribe(parent);
        
        //核心代码就是这句
        parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
    }

    static final class SubscribeOnObserver<T> extends AtomicReference<Disposable> implements Observer<T>, Disposable {
 
        //...省略其他代码...
        
        @Override
        public void onNext(T t) {
            actual.onNext(t);
        }

       
    }

    //核心代码
    final class SubscribeTask implements Runnable {
        private final SubscribeOnObserver<T> parent;

        SubscribeTask(SubscribeOnObserver<T> parent) {
            this.parent = parent;
        }

        @Override
        public void run() {
            source.subscribe(parent);
        }
    }
}

上記のsubscribeActualに戻ると、コードは次のとおりです。

public void subscribeActual(final Observer<? super T> s) {
    final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);

    s.onSubscribe(parent);

    parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}

最初にSubscribeOnObserver <T>親を作成し、 それを新しいSubscribeTaskに渡します

SubscribeTaskはRunnableを実装し、そのrunメソッドでsource.subscribe(parent)を実行します。 

 final class SubscribeTask implements Runnable {
        private final SubscribeOnObserver<T> parent;

        SubscribeTask(SubscribeOnObserver<T> parent) {
            this.parent = parent;
        }

        @Override
        public void run() {
            source.subscribe(parent);
        }
    }

次に、このRunnableをスケジューラscheduler.scheduleDirect(new SubscribeTask(parent))に渡します。 

スケジューラースケジューラーはどこにあるのか、Schedulers.ioフロントサブスクライブオン(スケジューラースケジューラー)が何を渡すかを覚えておいてください()。

次に、Schedulers.io()がどのように見えるかを見てください

    //源码点进去就是这个
  
    @NonNull
    public static Scheduler io() {
        return RxJavaPlugins.onIoScheduler(IO);
    }

 そして、RxJavaPlugins.onIoScheduler(IO)がソースコードをクリックして、返されたものがIOであることがわかりました。

@NonNull
    public static Scheduler onIoScheduler(@NonNull Scheduler defaultScheduler) {
        Function f = onIoHandler; //onIoHandler为null
        return f == null?defaultScheduler:(Scheduler)apply(f, defaultScheduler);
    }

IOとは何かがわかります

public final class Schedulers {
    
    ......

    @NonNull
    static final Scheduler IO;


    static {
        SINGLE = RxJavaPlugins.initSingleScheduler(new SingleTask());

        COMPUTATION = RxJavaPlugins.initComputationScheduler(new ComputationTask());

        // IO 在这里初始化
        IO = RxJavaPlugins.initIoScheduler(new IOTask());

        TRAMPOLINE = TrampolineScheduler.instance();

        NEW_THREAD = RxJavaPlugins.initNewThreadScheduler(new NewThreadTask());
    }


    ......

}

そしてRxJavaPlugins.initIoScheduler(new IOTask());最終的な戻り値はnew IOTask()の戻り値です。あなたは何と言いますか?

 

@NonNull
    public static Scheduler initIoScheduler(@NonNull Callable<Scheduler> defaultScheduler) {
        ObjectHelper.requireNonNull(defaultScheduler, "Scheduler Callable can\'t be null");
        Function f = onInitIoHandler;  //注释:onInitIoHandler为null 
        return f == null?callRequireNonNull(defaultScheduler):applyRequireNonNull(f, defaultScheduler);
    }

所以 RxJavaPlugins.initIoSchedule →  callRequireNonNull(defaultScheduler)(代码如下) 

@NonNull
    static Scheduler callRequireNonNull(@NonNull Callable<Scheduler> s) {
        try {
                                                         //s 
            return (Scheduler)ObjectHelper.requireNonNull(s.call(), "Scheduler Callable result can\'t be null");
        } catch (Throwable var2) {
            throw ExceptionHelper.wrapOrThrow(var2);
        }
    }

所以 callRequireNonNull(defaultScheduler) → ObjectHelper.requireNonNull(代码如下)
 
public final class ObjectHelper {

     public static <T> T requireNonNull(T object, String message) {
        if (object == null) {
            throw new NullPointerException(message);
        }
        return object; //注释 这个object就是s.call()  
    }

}

  次に、s.callメソッドが何であるかを見てみましょう 

 static final class IOTask implements Callable<Scheduler> {
        @Override
        public Scheduler call() throws Exception {
            return IoHolder.DEFAULT;
        }
    }

μIoHolder.DEFAULT= new IoScheduler();

 static final class IoHolder {
        static final Scheduler DEFAULT = new IoScheduler();
    }

也就是说最终为:
     Schedulers.io() =  new IoScheduler();

最後に、Schedulerから継承されたIoSchedulerを取得しました

public final class IoScheduler extends Scheduler {

.........................省略代码.............................


}

 

 

このようにして、両方の部分があります。次に、それらがどのように呼ばれるかを見ていきます。

呼び出しが開始される場所は、次のコード行です。subscribeActualのscheduler.scheduleDirect(new SubscribeTask(parent)

まず、IoSchedulerにはscheduleDirect メソッドがないことがわかりまし た。これは、親クラスのスケジューラに実装されているためです。

public abstract class Scheduler {
    
    @NonNull
    public Disposable scheduleDirect(@NonNull Runnable run) {
     注释: scheduler.scheduleDirect(new SubscribeTask(parent))先到这里
        return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
    }

    public abstract Worker createWorker();

    public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit 
       unit) {
        核心代码 ↓  createWorker在Scheduler中是抽象方法具体实现在子类IoScheduler中
        final Worker w = createWorker();

        final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);

        DisposeTask task = new DisposeTask(decoratedRun, w);
        
        这里就是子类createWorker得到 Worker w 调用schedule
        task就是subscribeOn创建的Runnable
        w.schedule(task, delay, unit);

        return task;
    }

}
public final class IoScheduler extends Scheduler {

    注释:createWorker创建并返回了一个EventLoopWorker对象
    public Worker createWorker() {
        return new EventLoopWorker(pool.get());
    }
    static final class EventLoopWorker extends Scheduler.Worker {
        
        private final ThreadWorker threadWorker;

        
        EventLoopWorker(CachedWorkerPool pool) {
            this.pool = pool;
            this.tasks = new CompositeDisposable();
            this.threadWorker = pool.get();
        }

        
        @NonNull
        @Override
        public Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull 
            TimeUnit unit) {
            if (tasks.isDisposed()) {
                // don't schedule, we are unsubscribed
                return EmptyDisposable.INSTANCE;
            }
            
            注释: threadWorker = pool.get(),
                  而pool.get()点进看到返回的是一个ThreadWorker
                  最终执行的是ThreadWorker.scheduleActual(action, delayTime, unit, tasks)
            return threadWorker.scheduleActual(action, delayTime, unit, tasks);
        }
    }
    static final class ThreadWorker extends NewThreadWorker {
        private long expirationTime;
        
        注释:但是在ThreadWorker 中并没有scheduleActual
             这个方法是在其父类NewThreadWorker中
        ThreadWorker(ThreadFactory threadFactory) {
            super(threadFactory);
            this.expirationTime = 0L;
        }

        public long getExpirationTime() {
            return expirationTime;
        }

        public void setExpirationTime(long expirationTime) {
            this.expirationTime = expirationTime;
        }
    }
      
}

以下のNewThreadWorkerソースコードを見てみましょう

public class NewThreadWorker extends Scheduler.Worker implements Disposable {

    public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull         
              TimeUnit unit, @Nullable DisposableContainer parent) {
        注释:这里将run 进行装饰封装最终传递到ScheduledRunnable sr中
        Runnable decoratedRun = RxJavaPlugins.onSchedule(run);

        ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);

        if (parent != null) {
            if (!parent.add(sr)) {
                return sr;
            }
        }

        Future<?> f;
        try {
            注释: sr在这里执行也,就是Runnable在这里执行
            还记得Runnable的run执行的是啥不: source.subscribe(parent);
             // @Override
             // public void run() {
             //    source.subscribe(parent);
             // }  
            if (delayTime <= 0) {
                f = executor.submit((Callable<Object>)sr);
            } else {
                f = executor.schedule((Callable<Object>)sr, delayTime, unit);
            }
            sr.setFuture(f);
        } catch (RejectedExecutionException ex) {
            if (parent != null) {
                parent.remove(sr);
            }
            RxJavaPlugins.onError(ex);
        }

        return sr;
    }

}

ここは、新しいスレッドsubscribeOn(Schedulers.io())を実行します。

実際、.subscribeが新しいスレッドで実行されることを除けば、flatMapやmapなどの他の操作と似ています。

注:最初のsubscribeOnのみが機能しますか?

上の図でわかるように、最初のsubscribeOnは新しいThread1を作成し、2番目のsubscribeOnは新しいThread2を作成します。

コールチェーンでは、最初に2番目のsubscribeOn実行し、Thread2に切り替えて.subscribeメソッドを実行し、次に最初のsubscribeOnに切り替えてThread1切り替えます。後続の.subscribe.onNextは、どちらも最初のsubscribeOnによって作成されたThread1スレッドにあります。実施した。したがって、最初のsubscribeOnのみが機能し、後続のsubscribeOnは効果がないとは言えません。.subscribeメソッドが実行されます。(それも役に立たないようです)。

================================================== ==============

以下をご覧ください

observeOn(AndroidSchedulers.mainThread()

また、2つの部分に分かれています

| ------ observeOn()はRunnable {run {.onNext()}}も作成し、それをに渡します

         AndroidSchedulers.mainThread()によって作成されたスレッドで呼び出されます。

| ------ AndroidSchedulers.mainThread()は、observeOnによって作成されたRunnableを実行するためのスレッドを返します。

最初にobserveOnを見てください

public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int 
     bufferSize) {
        ObjectHelper.requireNonNull(scheduler, "scheduler is null");
        ObjectHelper.verifyPositive(bufferSize, "bufferSize");
        return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, 
                                                                 delayError, bufferSize));
    }
        ↓ 接着看ObservableObserveOn


public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
         
     注释:scheduler就是我们传进来的AndroidSchedulers.mainThread()
     final Scheduler scheduler;
     
     public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean 
     delayError, int bufferSize) {
        super(source);
        this.scheduler = scheduler;
        ...
    }
    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
            注释:看这里 ↓
            Scheduler.Worker w = scheduler.createWorker();

            source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, 
                                                                     bufferSize));
        }
    }

}

 Scheduler.Worker w = Scheduler.createWorker()ご存知かどうかを確認してください

source.subscribe(new ObserveOnObserver <T>(observer、w、delayError、bufferSize));ここに直接。コントロール。

次に、ObserveOnObserverを見てみましょう。onNextがスレッドを切り替えてデータを転送する方法

注意:ObserveOnObserver实现的了Runnable,
static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
    implements Observer<T>, Runnable {

     final Scheduler.Worker worker;

     ObserveOnObserver(Observer<? super T> actual, Scheduler.Worker worker, boolean 
                 delayError, int bufferSize) {
            
            this.worker = worker;
             ...
        }

       @Override
        public void onNext(T t) {
            if (done) {
                return;
            }

            if (sourceMode != QueueDisposable.ASYNC) {
                queue.offer(t);
            }
            注释: 执行了这个方法
            schedule();
        }
        
       void schedule() {
            if (getAndIncrement() == 0) {
                注释:↓
                worker.schedule(this);
            }
        }
    
     public void run() {
            if (outputFused) {
                drainFused();
            } else {
                drainNormal();
            }
        }
     
     void drainNormal() {
           
            ...
            final Observer<? super T> a = actual;

            for (;;) {
                if (checkTerminated(done, q.isEmpty(), a)) {
                    return;
                }

                for (;;) {
                    
                    ......

                    a.onNext(v);

                }

               ......
            }
        }

}

 onNextでの実行はworker.schedule(this);です。

| ------ワーカー:scheduler.createWorker()

| ------これ:Runnableを実装するのはObserveOnObserver自体です

ここでobserveOnは終了し、ワーカー見つける必要があるのはcreateWorkerの方法です

次に、着信スケジューラ(実際には渡したAndroidSchedulers.mainThread)によって異なります。

 

AndroidSchedulers.mainThread()

public final class AndroidSchedulers { 

    public static Scheduler mainThread() {
        return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);
    }
            ↓ RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD)返回的就是MAIN_THREAD
    
   private static final Scheduler MAIN_THREAD = RxAndroidPlugins.initMainThreadScheduler(
           注释:这里看着也很熟悉,好像和Schedulers.io()差不多
             new Callable<Scheduler>() {
                @Override public Scheduler call() throws Exception {
                    return MainHolder.DEFAULT;
                }
            });
              ↓ 是的没错最后得到的就是MainHolder.DEFAULT

    private static final class MainHolder {
       static final Scheduler DEFAULT =
                     new HandlerScheduler(new Handler(Looper.getMainLooper()));
    }  
}

このようにして、AndroidSchedulers.mainThread()は、最終的にHandlerSchedulerオブジェクトである新しいHandler(Looper.getMainLooper())を取得します。

 HandlerSchedulerの構築パラメーターとして渡されます。

このようにして、スケジューラーを取得します。

次に、scheduler.createWorker()がどのように実装されているかを見てください

final class HandlerScheduler extends Scheduler {
     注释:这个handler就是new Handler(Looper.getMainLooper())
     private final Handler handler;

     HandlerScheduler(Handler handler) {
         this.handler = handler;
     }

    @Override
    public Worker createWorker() {
        注释1 ↓
        return new HandlerWorker(handler);
    }

  private static final class HandlerWorker extends Worker {
       
        private final Handler handler;
        
        HandlerWorker(Handler handler) {
            this.handler = handler;
        }

        @Override
        public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
            ...

            run = RxJavaPlugins.onSchedule(run);

            ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);

            Message message = Message.obtain(handler, scheduled);
            message.obj = this; 

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

            ...

            return scheduled;
        }

}

ワーカーを見つけることができるように、HandlerWorkerオブジェクトがcreateWorkerに返されます。

 onNext→schedule()を覚えて、スケジュールでworker.schedule(Runnable)を呼び出します

ただし、この実装は親クラスのScheduler.Workerにあるため、HandlerWorkerにはschedule(Runnable run)メソッドがありません。

public abstract class Scheduler {
  
  public abstract static class Worker implements Disposable {

        @NonNull
        public Disposable schedule(@NonNull Runnable run) {

            注释 schedule(run, 0L, TimeUnit.NANOSECONDS)是下面的抽象方法
                 具体实现在其子类中,所以又回到了原来的HandlerWorker
            return schedule(run, 0L, TimeUnit.NANOSECONDS);
        }
    
   
    @NonNull
    public abstract Disposable schedule(@NonNull Runnable run, long delay, TimeUnit unit);

 
  }
}

上記のHandlerWorkerのソースコードを覚えていますか?

  private static final class HandlerWorker extends Worker {
       
        private final Handler handler;
        
        HandlerWorker(Handler handler) {
            this.handler = handler;
        }

        @Override
        public Disposable schedule(Runnable run, long delay, TimeUnit unit) {
            ...

            run = RxJavaPlugins.onSchedule(run);

            ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);
            
            注释: 核心代码
            Message message = Message.obtain(handler, scheduled);
            
            message.obj = this; 

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

            ...

            return scheduled;
        }

ハンドラーを使用してRunnableを実行用のメインスレッドに配置し、メインスレッドに切り替えられるようにします(ここではAndroidSchedulers.mainThread()を渡します)

このようにして、Runnableのrunメソッドはメインスレッドで実行されました

この時点で、Runnableのrunメソッド(つまり、ObserveOnObserver)がどのように実行されるかを確認できます。

static final class ObserveOnObserver<T> extends BasicIntQueueDisposable<T>
    implements Observer<T>, Runnable {

    ...省略其它代码...

     public void run() {
            if (outputFused) {
                不走这里 这里执行的是onNext(null)传一个null回去
                drainFused();
            } else {
                执行这里
                drainNormal();
            }
        }
     
     void drainNormal() {
           
            ...
            final Observer<? super T> a = actual;

            for (;;) {
                if (checkTerminated(done, q.isEmpty(), a)) {
                    return;
                }

                for (;;) {
                    
                    ......
                    终于,数据在我们observeOn的线程中传递了回去
                    a.onNext(v);

                }

               ......
            }
        }

}

このようにして、observeOn(AndroidSchedulers.mainThread()は終了します。

注:Rxjvavaは、サブスレッドとメインスレッドを切り替えることができるため、柔軟性があります。

スレッドを柔軟に切り替えるobserveOnのコアコードは次のとおりです

public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> { 
   
  @Override
    protected void subscribeActual(Observer<? super T> observer) {
        if (scheduler instanceof TrampolineScheduler) {
            source.subscribe(observer);
        } else {
   核心代码
   Scheduler.Worker w = scheduler.createWorker();

   source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));

        }
    }

observeOnでScheduler.newThread()を渡すと、スケジューラーはNewThreadSchedulerになり、scheduler.createWorker()はNewThreadWorkerを取得し、次にexecutor.submit(Runnable)を取得します。

observeOnでScheduler.io()を渡すと、スケジューラーはIoSchedulerになり、scheduler.createWorker()はEventLoopWorkerを取得し、次にexecutor.submit(Runnable)を取得します。

observeOnでAndroidSchedulers.mainThread()を渡すと、スケジューラーはHandlerScheduler(new Handler(Looper.getMainLooper()))になり、scheduler.createWorker()はHandlerWorkerを取得して実行します。

Message message = Message.obtain(handler, scheduled);
message.obj = this;  
handler.sendMessageDelayed(message, unit.toMillis(delay));

この時点で、スレッドを切り替える方法は終わりました。

 

おすすめ

転載: blog.csdn.net/u011288271/article/details/108006371