RxJava2.X源码分析(二):探索RxJava2之订阅线程切换原理

前言

基于RxJava2.1.1
我们在前面的 RxJava2.0使用详解(一)初步分析了RxJava从创建到执行的流程。也明白了RxJava的onComplete();与onError(t);只有一个会被执行的秘密。
本次我们将探索RxJava2.x线程切换的实现原理。做到知其然,知其所以然。
Ok,开始我们的探索之旅吧!

从Demo到源码

先来看看没有切换线程的demo:

Observable.create(new ObservableOnSubscribe<Integer>() {
    
    

    @Override
    public void subscribe(ObservableEmitter<Integer> e) throws Exception {
    
    
        Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
        e.onNext(123);
  Log.d("MainActivity","onNext(发送) :"+ "123");
    }
})
        .subscribe(new Observer<Integer>() {
    
    
    @Override
    public void onSubscribe(Disposable d) {
    
    

    }

    @Override
    public void onNext(Integer integer) {
    
    
        Log.d("MainActivity","onNext(接收) :"+integer + "");
        Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
    }

    @Override
    public void onError(Throwable e) {
    
    

    }

    @Override
    public void onComplete() {
    
    

    }
});


====================================
结果是:
2021-01-23 16:27:02.667 16788-16788/com.damon.myapplication D/MainActivity: 工作线程是:main
2021-01-23 16:27:02.668 16788-16788/com.damon.myapplication D/MainActivity: onNext(发送) :123
2021-01-23 16:27:02.668 16788-16788/com.damon.myapplication D/MainActivity: 工作线程是:main
2021-01-23 16:27:02.668 16788-16788/com.damon.myapplication D/MainActivity: onNext(接收) :123



再来看看有切换线程功能的版本:

 Observable.create(new ObservableOnSubscribe<Integer>() {
    
    

            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
    
    
                Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
                Log.d("MainActivity","onNext(发送) :"+ "123");
                e.onNext(123);

            }
        }).subscribeOn(Schedulers.io())
                .observeOn(Schedulers.io())
                .subscribe(new Observer<Integer>() {
    
    
            @Override
            public void onSubscribe(Disposable d) {
    
    
                Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
                Log.d("MainActivity","onSubscribe :");
            }

            @Override
            public void onNext(Integer integer) {
    
    
                Log.d("MainActivity","工作线程是:"+Thread.currentThread().getName());
                Log.d("MainActivity","onNext(接收) :"+integer + "");

            }

            @Override
            public void onError(Throwable e) {
    
    

            }

            @Override
            public void onComplete() {
    
    

            }
        });

=======================================
结果是:
2021-01-25 10:59:51.859 3508-3508/com.damon.myapplication D/MainActivity: 工作线程是:main
2021-01-25 10:59:51.859 3508-3508/com.damon.myapplication D/MainActivity: onSubscribe :
2021-01-25 10:59:51.871 3508-3691/com.damon.myapplication D/MainActivity: 工作线程是:RxCachedThreadScheduler-1
2021-01-25 10:59:51.871 3508-3691/com.damon.myapplication D/MainActivity: onNext(发送) :123
2021-01-25 10:59:51.872 3508-3694/com.damon.myapplication D/MainActivity: 工作线程是:RxCachedThreadScheduler-2
2021-01-25 10:59:51.872 3508-3694/com.damon.myapplication D/MainActivity: onNext(接收) :123


很显然,Observer的onSubsriber()在那个线程调用,就在那个线程执行(此时是在Main线程里调用),发送事件和接收事件都会另外开一个Io线程来执行。
OK,现象看完了,我们开始看本质吧!但是,从哪入手呢?还是老办法,哪里触发的行为就哪里下手( ̄∇ ̄)
OK,我们先来探索切换Observable工作线程的subscribeOn方法入手:

Class Observable{
    
    
......
    @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));
    }
    
    }

看到了RxJavaPlugins.onAssembly,前面分析过,为hook服务,现在看成是返回传入的Obserable即可。这里的this为我们的observable,scheduler就是我们传入的Schedulers.io();我们继续看ObservableSubscribeOn:

public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    
    ....}

其继承AbstractObservableWithUpstream:

 abstract class AbstractObservableWithUpstream<T, U> extends Observable<U> implements HasUpstreamObservableSource<T> {
    
    

        /** The source consumable Observable. */
      protected final ObservableSource<T> source;

        /**
     * Constructs the ObservableSource with the given consumable. * @param source the consumable Observable
     */  AbstractObservableWithUpstream(ObservableSource<T> source) {
    
    
            this.source = source;
        }

        @Override
      public final ObservableSource<T> source() {
    
    
            return source;
        }

    }

AbstractObservableWithUpstream继承自Observable,其作用是通过source字段保存上游的Observable,因为Observable是ObservableSource接口的实现类,所以我们可以认为Observable和ObservableSource在本文中是相等的:,
也就是说ObservableSubscribeOn是对Observble进行了一次wrapper操作
OK,我们继续回来看ObservableSubscribeOn的源码:

  public final class ObservableSubscribeOn<T> extends AbstractObservableWithUpstream<T, T> {
    
    
      //1、线程调度器
      final Scheduler scheduler;
      public ObservableSubscribeOn(ObservableSource<T> source, Scheduler scheduler) {
    
    
          //2、存储上游的obserble
          super(source);
          this.scheduler = scheduler;
      }

      @Override
    public void subscribeActual(final Observer<? super T> s) {
    
    
        //以下为关键部分
          //3、对我们下游的observer进行一次wrapper
          final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(s);
          //4、同样,先自己调用自己的onSubscribe
          s.onSubscribe(parent);
          //5、(高能量聚集了)将调度的线程的Disposable赋值给当前的Disposable。scheduler可以看成是某个线程上的调度器。new SubscribeTask(parent)工作在其指定的线程里面。SubscribeTask是一个Runnable,也就是说调度器触发Runnable的run()运行,
          //***是不是恍然大悟,那么run()里面的代码就是运行在scheduler的线程上了。这样也就实现了线程的切换了。
          parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
      }
      static final class SubscribeOnObserver<T> extends AtomicReference implements Observer<T>, Disposable {
    
    ....}
      ...
      }

继续看一下ObservableSubscribeOn的内部类SubscribeOnObserver:

static final class SubscribeOnObserver<T> extends AtomicReference<Disposable> implements Observer<T>, Disposable {
    
    

        private static final long serialVersionUID = 8094547886072529208L;
        final Observer<? super T> actual;

        final AtomicReference<Disposable> s;

        SubscribeOnObserver(Observer<? super T> actual) {
    
    
            this.actual = actual;
            this.s = new AtomicReference<Disposable>();
        }

        @Override
        public void onSubscribe(Disposable s) {
    
    
            DisposableHelper.setOnce(this.s, s);
        }

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

        @Override
        public void onError(Throwable t) {
    
    
            actual.onError(t);
        }

        @Override
        public void onComplete() {
    
    
            actual.onComplete();
        }

        @Override
        public void dispose() {
    
    
            DisposableHelper.dispose(s);
            DisposableHelper.dispose(this);
        }

        @Override
        public boolean isDisposed() {
    
    
            return DisposableHelper.isDisposed(get());
        }

        void setDisposable(Disposable d) {
    
    
            DisposableHelper.setOnce(this, d);
        }
    }

SubscribeOnObserver实现了observer,且构造器中传入了一个observer类型的参数,说明这个类主要的作用就是对下游的observer进行一次包装,从重写的方法来看,也证实了这一点,都调用了下游observer里的相对应的方法。
Ok,我们继续看SubscribeTask这个类:

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

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

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

parent就是我们包装后的observer,其内部保存了下游的observer

source即通过ObservableSubscribeOnwrapper后存储我们上游的observable

所以run里面的source.subscribe(parent);即为wrapper的observer订阅了上游的observable,触发了上游observable的subscribeActual,开始执行数据的分发。

具体可以下图:

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210125194618566.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5NDMxNDA1,size_16,color_FFFFFF,t_70在这里插入图片描述
在这里插入图片描述
思路梳理(重要)
Ok,分析到这里思路基本清晰了
1、在执行subscribeOn时,在Observable和observer中插入了一个(wrapper)obserabler和(wrapper)Observer
原observable->【(Wrapper)observable||(Wrapper)Observer】->(原)Observer

2、observable.subscribe触发->(Wrapper)Observable.subscribeActual()内部调用->parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));,->scheduler在指定线程调用(完成线程切换)->SubscribeTask.run,run内部调用->原Observable.subscribe((Wrapper)Observer)触发->(原)Observable.subscribeActual()开始数据分发
Ok,此时分发给的是(Wrapper)Observer,那应该是(Wrapper)Observer分发给了(原)Observer。


Ok,有了对SubscribeOnObserver分析的铺垫,我们现在可以分析一下

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

我们先看scheduler.scheduleDirect()这句

   @NonNull
   //以毫秒为单位,无延迟调度
    public Disposable scheduleDirect(@NonNull Runnable run) {
    
    
        return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
    }

其返回一个Disposable,我们看下这个Disposable是否真的是调度的线程的。

@NonNull
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    
    
  @NonNull
  public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
    
    
      //13、Worker实现了Disposable的一个调度工作者类
      final Worker w = createWorker();
      //14、hook,排除hook干扰,可以理解为decoratedRun==run
      final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
      //15、DisposeTask同样是实现了Disposable的Task
      DisposeTask task = new DisposeTask(decoratedRun, w);
      //16、开始执行
      w.schedule(task, delay, unit);
      //17、确实是返回了管理run的worker
      return task;
  }
}

Ok,现在终点转移到DisposeTask,我们把run给了DisposeTask,然后worker调度task开始执行run

OK,那么我们可以猜测w.schedule(task, delay, unit)执行后应该是调度了task的某个方法,然后task开始执行Runnable的run

是不是真的呢?我们来看下new DisposeTask(decoratedRun, w)做了什么

  static final class DisposeTask implements Runnable, Disposable {
    
    
      //18、我们外部传入的runnable
      final Runnable decoratedRun;
      //19、调度工作者
      final Worker w;
      //20、当前线程
      Thread runner;
      DisposeTask(Runnable decoratedRun, Worker w) {
    
    
          this.decoratedRun = decoratedRun;
          this.w = w;
      }

      @Override
    public void run() {
    
    
          //21、获取执decoratedRun的线程
          runner = Thread.currentThread();
          try {
    
    
            //22、OK,高能来了。decoratedRun的run被执行
              decoratedRun.run();
          } finally {
    
    
              dispose();
              runner = null;
          }
      }

      @Override
    public void dispose() {
    
    

          if (runner == Thread.currentThread() && w instanceof NewThreadWorker) {
    
    
              ((NewThreadWorker)w).shutdown();
          } else {
    
    
              //在DisposeTask被取消时,告诉Worker取消,因为DisposeTask是Worker进行管理的
              w.dispose();
          }
      }

      @Override
    public boolean isDisposed() {
    
    
          return w.isDisposed();
      }
  }

结论:
scheduler.scheduleDirect无延迟调用->worker->worker调度->DisposeTask->DisposeTask.run执行->decoratedRun.run();

decoratedRun即我们外部的SubscribeTask

猜你喜欢

转载自blog.csdn.net/qq_39431405/article/details/113055137