RXjava响应式编程

此文作者大暴雨原创,转载请注明出处。

如果线程的知识不是很丰富,请先查看     rxjava源码中的线程知识  一文

rxjava总结就是:异步
实现主要是通过扩展观察者模式

首先我们看一下只有一条线程是怎么实现响应式的。这比较简单。首先看一下Observable这个类(被观察者),还有Subscriber (观察者),Subscriber实现了Observer 类。

Observable从create开始

public static <T> Observable<T> create(OnSubscribe<T> f) {
        return new Observable<T>(hook.onCreate(f));
    }
    create方法就是new一个Observable对象,参数是hook.onCreate(f)。hook是RxJavaObservableExecutionHook类,RxJavaObservableExecutionHook这个类什么也没有做就是传进去什么参数,返回什么。所以这里的hook.onCreate(f),返回的就是f对象,就是OnSubscribe。
    
    
    再看一下Observable的构造方法,参数是OnSubscribe获取

protected Observable(OnSubscribe<T> f) {
        this.onSubscribe = f;
    }
    Observable的构造方法就是为了获取订阅对象

看一下观察者和被观察者是怎么联系的。执行订阅的方法就会执行subscribe.call方法.
   private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {
        
        ...
        ...
        
        subscriber.onStart();
        
        ...
        
        try {
            // allow the hook to intercept and/or decorate
            hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);
            return hook.onSubscribeReturn(subscriber);
        } catch (Throwable e) {
           ...
        }
    }

首先调用subscriber.onStart();这个onstart要自己重写,因为这个onStart方法,默认是空的,什么也没有做。最后调用hook.onSubscribeStart(observable,observable.onSubscribe).call(subscriber);hook.onSubscribeStart这返回的observable.onSubscribe这个参数,之前已经说过,hook是什么也没有干的,你传什么参数进去就返回什么。实际上就是observable.onSubscribe的call方法。onSubscribe这个接口继承自Action1,action1的call方法然后再拆分为不同的接口,例如onNext(),onCompleted(),onError()。这样就实现了从创建到触发call回调了。接下来看一下多线程,响应式是怎么实现的。毕竟异步才是响应式的核心。

响应式多线程的实现

1.调用的方式

指定事件在哪个线程执行:subscribeOn(Scheduler scheduler)
    指定事件的响应在哪个线程:observeOn(Scheduler scheduler)

首先看参数是Scheduler调度器。调度器的类型Schedulers这个类。
    
    
    public final class Schedulers {

private final Scheduler computationScheduler;
        private final Scheduler ioScheduler;
        private final Scheduler newThreadScheduler;

private static final Schedulers INSTANCE = new Schedulers();

private Schedulers() {
            Scheduler c = RxJavaPlugins.getInstance().getSchedulersHook().getComputationScheduler();
            if (c != null) {
                computationScheduler = c;
            } else {
                computationScheduler = new EventLoopsScheduler();
            }

Scheduler io = RxJavaPlugins.getInstance().getSchedulersHook().getIOScheduler();
            if (io != null) {
                ioScheduler = io;
            } else {
                ioScheduler = new CachedThreadScheduler();
            }

Scheduler nt = RxJavaPlugins.getInstance().getSchedulersHook().getNewThreadScheduler();
            if (nt != null) {
                newThreadScheduler = nt;
            } else {
                newThreadScheduler = NewThreadScheduler.instance();
            }
        }
        
        省略一些get类,和测试类
        ...
        ...
    
    }
    
    这里可以看到rxjava提供三种线程,android有多一些。Schedulers是一个单列的。RxJavaPlugins.getInstance().getSchedulersHook()这个类和hook是一样的,传什么就返回什么,不传就返回null。所以这里一定是跑else的代码。

接下来已io为例,看一下初始化Scheduler。CachedThreadScheduler继承Scheduler。

final class CachedThreadScheduler extends Scheduler implements SchedulerLifecycle {
    
    private static final String WORKER_THREAD_NAME_PREFIX = "RxCachedThreadScheduler-";
    
    一些初始化的操作,略
    ...
    
    
    //缓存线程的操作
    private static final class CachedWorkerPool {
        private final long keepAliveTime;
        private final ConcurrentLinkedQueue<ThreadWorker> expiringWorkerQueue;
        private final CompositeSubscription allWorkers;//保存正在使用的subscriptions
        private final ScheduledExecutorService evictorService;
        
        private final Future<?> evictorTask;

CachedWorkerPool(long keepAliveTime, TimeUnit unit) {
            this.keepAliveTime = unit != null ? unit.toNanos(keepAliveTime) : 0L;
            this.expiringWorkerQueue = new ConcurrentLinkedQueue<ThreadWorker>();
            this.allWorkers = new CompositeSubscription();

ScheduledExecutorService evictor = null;
            Future<?> task = null;
            if (unit != null) {
                evictor = Executors.newScheduledThreadPool(1, EVICTOR_THREAD_FACTORY);
                NewThreadWorker.tryEnableCancelPolicy(evictor);
                task = evictor.scheduleWithFixedDelay(
                        new Runnable() {
                            @Override
                            public void run() {
                                evictExpiredWorkers();
                            }
                        }, this.keepAliveTime, this.keepAliveTime, TimeUnit.NANOSECONDS
                );
            }
            evictorService = evictor;
            evictorTask = task;
        }

ThreadWorker get() {
            
            if (allWorkers.isUnsubscribed()) {
                return SHUTDOWN_THREADWORKER;
            }
            //从队列去找
            while (!expiringWorkerQueue.isEmpty()) {
                ThreadWorker threadWorker = expiringWorkerQueue.poll();
                if (threadWorker != null) {
                    return threadWorker;
                }
            }

// No cached worker found, so create a new one.
            //没有worker,就new一个
            ThreadWorker w = new ThreadWorker(WORKER_THREAD_FACTORY);
            
            //添加到缓存allWorkers中
            allWorkers.add(w);
            return w;
        }

void release(ThreadWorker threadWorker) {
            // Refresh expire time before putting worker back in pool
            threadWorker.setExpirationTime(now() + keepAliveTime);
            //插入队列尾部
            expiringWorkerQueue.offer(threadWorker);
        }
        //移除当前除了当前外的ThreadWorker。
        void evictExpiredWorkers() {
            if (!expiringWorkerQueue.isEmpty()) {
                long currentTimestamp = now();

for (ThreadWorker threadWorker : expiringWorkerQueue) {
                    if (threadWorker.getExpirationTime() <= currentTimestamp) {
                        if (expiringWorkerQueue.remove(threadWorker)) {
                            allWorkers.remove(threadWorker);
                        }
                    } else {
                        // Queue is ordered with the worker that will expire first in the beginning, so when we
                        // find a non-expired worker we can stop evicting.
                        break;
                    }
                }
            }
        }

...
    }

final AtomicReference<CachedWorkerPool> pool;
    
    static final CachedWorkerPool NONE;
    static {
        NONE = new CachedWorkerPool(0, null);
        NONE.shutdown();
    }
    
    public CachedThreadScheduler() {
        this.pool = new AtomicReference<CachedWorkerPool>(NONE);
        start();
    }
    
    ...
    ...
    
    @Override
    public Worker createWorker() {
        return new EventLoopWorker(pool.get());
    }

//线程操作的类
    private static final class EventLoopWorker extends Scheduler.Worker {
        private final CompositeSubscription innerSubscription = new CompositeSubscription();//保存正在使用的subscriptions
        private final CachedWorkerPool pool;//缓存线程
        private final ThreadWorker threadWorker;
        @SuppressWarnings("unused")
        volatile int once;
        static final AtomicIntegerFieldUpdater<EventLoopWorker> ONCE_UPDATER
                = AtomicIntegerFieldUpdater.newUpdater(EventLoopWorker.class, "once");

EventLoopWorker(CachedWorkerPool pool) {
            this.pool = pool;
            this.threadWorker = pool.get();//获取工作线程
        }

@Override
        public void unsubscribe() {
            if (ONCE_UPDATER.compareAndSet(this, 0, 1)) {
                // unsubscribe should be idempotent, so only do this once
                pool.release(threadWorker);//插入线程
            }
            innerSubscription.unsubscribe();
        }

@Override
        public boolean isUnsubscribed() {
            return innerSubscription.isUnsubscribed();
        }

@Override
        public Subscription schedule(Action0 action) {
            return schedule(action, 0, null);
        }

@Override
        public Subscription schedule(Action0 action, long delayTime, TimeUnit unit) {
            if (innerSubscription.isUnsubscribed()) {
                // don't schedule, we are unsubscribed
                return Subscriptions.unsubscribed();
            }
            //这个是真正执行任务的线程
            ScheduledAction s = threadWorker.scheduleActual(action, delayTime, unit);//执行线程,把action关联起来
            
            innerSubscription.add(s);
            s.addParent(innerSubscription);
            
            
            return s;
        }
    }

private static final class ThreadWorker extends NewThreadWorker {
        private long expirationTime;

ThreadWorker(ThreadFactory threadFactory) {
            super(threadFactory);
            this.expirationTime = 0L;
        }
        
        public long getExpirationTime() {
            return expirationTime;
        }

public void setExpirationTime(long expirationTime) {
            this.expirationTime = expirationTime;
        }
    }
}
    
    
    这里有两个内部类,CachedWorkerPool和EventLoopWorker这两个类。CachedWorkerPool是缓存线程,把ThreadWorker放到队列里面,提供一些操作的方法,例如get方法获取ThreadWorker对象,还有一些插入,清除等操作。EventLoopWorker线程的操作类,首先从缓存线程中取出一个ThreadWorker,在schedule方法中实现了threadWorker.scheduleActual这个方法,这个方法就是真正执行任务的线程。接着简要看一下threadWorker.scheduleActual这个方法。
    
    threadWorker类的scheduleActual方法:
    
     public ScheduledAction scheduleActual(final Action0 action, long delayTime, TimeUnit unit) {
        Action0 decoratedAction = schedulersHook.onSchedule(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;
    }
    
    ScheduledAction的run方法:
    public void run() {
        try {
            lazySet(Thread.currentThread());
            action.call();
        } catch (Throwable e) {
            // nothing to do but print a System error as this is fatal and there is nowhere else to throw this
            IllegalStateException ie = null;
            if (e instanceof OnErrorNotImplementedException) {
                ie = new IllegalStateException("Exception thrown on Scheduler.Worker thread. Add `onError` handling.", e);
            } else {
                ie = new IllegalStateException("Fatal Exception thrown on Scheduler.Worker thread.", e);
            }
            RxJavaPlugins.getInstance().getErrorHandler().handleError(ie);
            Thread thread = Thread.currentThread();
            thread.getUncaughtExceptionHandler().uncaughtException(thread, ie);
        } finally {
            unsubscribe();
        }
    }
    
    cheduledAction这个类是执行的线程,这个类就是把action和线程绑定,在线程中调用action.call()方法。这里启动executor线程池,执行任务,run.add(f)线程执行结果添加到cheduledAction中。这样子就能在一个线程中执行call方法。
    
    这里是以io为例,所有都是继承Scheduler类的,所以看一下Scheduler这个类。

public abstract class Scheduler {

static final long CLOCK_DRIFT_TOLERANCE_NANOS;
    static {
        CLOCK_DRIFT_TOLERANCE_NANOS = TimeUnit.MINUTES.toNanos(
                Long.getLong("rx.scheduler.drift-tolerance", 15));
    }
    
   
    public abstract Worker createWorker();

public abstract static class Worker implements Subscription {

public abstract Subscription schedule(Action0 action);

public abstract Subscription schedule(final Action0 action, final long delayTime, final TimeUnit unit);

public Subscription schedulePeriodically(final Action0 action, long initialDelay, long period, TimeUnit unit) {
            final long periodInNanos = unit.toNanos(period);
            final long firstNowNanos = TimeUnit.MILLISECONDS.toNanos(now());
            final long firstStartInNanos = firstNowNanos + unit.toNanos(initialDelay);

final MultipleAssignmentSubscription mas = new MultipleAssignmentSubscription();
            final Action0 recursiveAction = new Action0() {
                long count;
                long lastNowNanos = firstNowNanos;
                long startInNanos = firstStartInNanos;
                @Override
                public void call() {
                    if (!mas.isUnsubscribed()) {
                        action.call();
                        
                        long nextTick;
                        
                        long nowNanos = TimeUnit.MILLISECONDS.toNanos(now());
                        
                        if (nowNanos + CLOCK_DRIFT_TOLERANCE_NANOS < lastNowNanos
                                || nowNanos >= lastNowNanos + periodInNanos + CLOCK_DRIFT_TOLERANCE_NANOS) {
                            nextTick = nowNanos + periodInNanos;
                            
                            startInNanos = nextTick - (periodInNanos * (++count));
                        } else {
                            nextTick = startInNanos + (++count * periodInNanos);
                        }
                        lastNowNanos = nowNanos;
                        
                        long delay = nextTick - nowNanos;
                        mas.set(schedule(this, delay, TimeUnit.NANOSECONDS));
                    }
                }
            };
            MultipleAssignmentSubscription s = new MultipleAssignmentSubscription();
            // Should call `mas.set` before `schedule`, or the new Subscription may replace the old one.
            mas.set(s);
            s.set(schedule(recursiveAction, initialDelay, unit));
            return mas;
        }

public long now() {
            return System.currentTimeMillis();
        }
    }

public long now() {
        return System.currentTimeMillis();
    }
    
    在父类可以看到,createWorker,创建一个EventLoopWorker,然后就是调用Worker的schedulePeriodically方法也会调用schedule方法,去执行任务。上面已经说了,schedule方法就是通过从缓存队列中获取ThreadWorker,然后执行scheduleActual方法。去实现在线程中执行任务。我们已经理解了参数Scheduler,这个时候看看怎么用这个调度器类。
    
    指定事件在哪个线程执行:subscribeOn(Scheduler scheduler)
    
    public final Observable<T> observeOn(Scheduler scheduler) {
        if (this instanceof ScalarSynchronousObservable) {
            return ((ScalarSynchronousObservable<T>)this).scalarScheduleOn(scheduler);
        }
        return lift(new OperatorObserveOn<T>(scheduler, false));
    }
    
    首先看一下ScalarSynchronousObservable.scalarScheduleOn方法
    
     public Observable<T> scalarScheduleOn(final Scheduler scheduler) {
        final Func1<Action0, Subscription> onSchedule;
        if (scheduler instanceof EventLoopsScheduler) {
            final EventLoopsScheduler els = (EventLoopsScheduler) scheduler;
            onSchedule = new Func1<Action0, Subscription>() {
                @Override
                public Subscription call(Action0 a) {
                    return els.scheduleDirect(a);
                }
            };
        } else {
            onSchedule = new Func1<Action0, Subscription>() {
                @Override
                public Subscription call(final Action0 a) {
                    final Scheduler.Worker w = scheduler.createWorker();
                    w.schedule(new Action0() {
                        @Override
                        public void call() {
                            try {
                                a.call();
                            } finally {
                                w.unsubscribe();
                            }
                        }
                    });
                    return w;
                }
            };
        }
        
        return create(new ScalarAsyncOnSubscribe<T>(t, onSchedule));
    }
    
    可以看到,如果是EventLoopsScheduler,就直接创建Func1,如果不是,我们举例io就不是EventLoopsScheduler,是CachedThreadScheduler,就是跑else代码,scheduler.createWorker(),创建一个Worker,然后执行schedule,schedule方法已经说了,就是指定线程执行。在线程的call方法中执行onSchedule.call()回调。
    
    
    源码分析到此处。如果哪里有错误,请指出谢谢。
    
    
    此文作者大暴雨原创,转载请注明出处。

rxjava源码分析的更多相关文章

  1. RxJava 2.x 源码分析

    本次分析的 RxJava 版本信息如下: 12 implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'implementation 'io.reac ...

  2. Retrofit源码分析(一)

    1.基本用法 创建接口 public interface GitHubService { @GET("users/{user}/repos") Observable<List ...

  3. RxJava系列6(从微观角度解读RxJava源码)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  4. RxJava2 中多种取消订阅 dispose 的方法梳理( 源码分析 )

    Github 相关代码: Github地址 一直感觉 RxJava2 的取消订阅有点混乱, 这样也能取消, 那样也能取消, 没能系统起来的感觉就像掉进了盘丝洞, 迷乱… 下面说说这几种情况 几种取消的 ...

  5. Android进阶——多线程系列之异步任务AsyncTask的使用与源码分析

    AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并主线程中更新UI,通过AsyncTask可以更加方便执行后台任务以及在主线程中访问UI ...

  6. hystrix 源码分析以及属性的配置

    一.feign与hystix结合 1.1测试环境搭建 架构如图: 非常简单,就是Order服务通过feign调用product服务的一个获取商品信息的一个接口: package com.yang.xi ...

  7. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  8. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  9. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

随机推荐

  1. Android moveTaskToBack(booleannon Root)

    moveTaskToBack (booleannon Root)方法:在activity中调用此方法即可将activity 退到后台,注意不是finish()退出. 参数说明: 参数为false--代 ...

  2. 在Page_Loaded下删除PivotItem出错的解决方案

    之前我一个例子中出现无法再页面Loaded事件中删除PivotItem的情况,页面会报错 Value does not fall within the expected range. 附图 原因是因为 ...

  3. 用于基于 RPM 的 Linux 平台的 Java

    成为超级用户,方法是运行 su 并输入超级用户口令. 卸载任何之前安装的 Java 程序包. rpm -e package_name 切换到所需的安装目录.键入:cd directory_path_n ...

  4. Cef 架构

    cef支持各种语言和多种操作系统.在设计的时候充分考虑了性能和易用性.cef核心功能提供了c和c++的接口.cef提供了和主程序之间的通信能力(利用 custom plugins, protocols ...

  5. 在Ubuntu上安装有道词典

    4月20日,由有道词典和Deepin团队共同完成的有道词典Linux版终于上线了,首先 推出Deepin和Ubuntu两个系统版本及其他版本的二进制包,估计以后还会有RPM 等版本.有道Linux版界 ...

  6. mysql索引的使用和优化

    参考: http://blog.csdn.net/xluren/article/details/32746183 http://www.cnblogs.com/hustcat/archive/2009 ...

  7. install phpexcel using composer in thinkPHP

    Environment Window 10.1 XAMPP 7.0.9 (PHP 7.0.9) thinkPHP 5.0.1 Steps # visit https://getcomposer.org ...

  8. linux date时区修改

    # vi /etc/sysconfig/clock ZONE=Asia/Shanghai(查/usr/share/zoneinfo下面的文件)   [root@localhost ~]# dateFr ...

  9. Centos7下用命令同步标准时间

    新装的CentO7S系统服务器可能设置了错误的时间,需要调整时区和时间.如下是CentOS7系统使用NTP协议,从一个时间服务器同步标准时间: [root@localhost ~]# cp /usr/ ...

  10. quick-cocos2d-x 实现在lua里面完成android支付宝的接入

    quick-cocos2d-x 实现在lua里面完成android支付宝的接入 一.支付宝注册是很麻烦的一个过程,本文就不解释了,想了解的去官网看下注册流程.然后下载他们的sdk-WS_SECURE_ ...