rxjava源码分析
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源码分析的更多相关文章
- RxJava 2.x 源码分析
本次分析的 RxJava 版本信息如下: 12 implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'implementation 'io.reac ...
- Retrofit源码分析(一)
1.基本用法 创建接口 public interface GitHubService { @GET("users/{user}/repos") Observable<List ...
- RxJava系列6(从微观角度解读RxJava源码)
RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...
- RxJava2 中多种取消订阅 dispose 的方法梳理( 源码分析 )
Github 相关代码: Github地址 一直感觉 RxJava2 的取消订阅有点混乱, 这样也能取消, 那样也能取消, 没能系统起来的感觉就像掉进了盘丝洞, 迷乱… 下面说说这几种情况 几种取消的 ...
- Android进阶——多线程系列之异步任务AsyncTask的使用与源码分析
AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并主线程中更新UI,通过AsyncTask可以更加方便执行后台任务以及在主线程中访问UI ...
- hystrix 源码分析以及属性的配置
一.feign与hystix结合 1.1测试环境搭建 架构如图: 非常简单,就是Order服务通过feign调用product服务的一个获取商品信息的一个接口: package com.yang.xi ...
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- nginx源码分析之网络初始化
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...
随机推荐
- 基于Android的手机APP
文档链接: https://coding.net/u/lingyu512/p/document/git/blob/master/%E7%AC%AC6%E7%BB%84_%E8%BF%9B%E5%87% ...
- html中input标签的tabindex属性
当浏览者浏览网站时可以通过按TAB键在网页的链接中依次移动,这是一个相当方便实用的功能.但如果网页中链接太多,恐怕按TAB键就没什么作用了,这时不妨通过改变TAB键移动的顺序来突出重点,在某些重要页面 ...
- Opennms 问题整理
1.网页时间显示不正确,需要修改:bin/opennms: 添加:MANAGER_OPTIONS="$MANAGER_OPTIONS -Duser.timezone=Asia/Shangha ...
- java 日期转时间戳,时间戳转为日期
package date; import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Dat ...
- gulp 安装 使用 和删除
1.安装 全局安装: npm intstall gulp -g (首先你得有node.js ,这个可以去node 官网下载个iso的镜像安装包,傻瓜式安装.自带npm) 安装在项目中: 首先 ...
- Python GIL 多线程机制 (C source code)
最近阅读<Python源码剖析>对进程线程的封装解释: GIL,Global Interpreter Lock,对于python的多线程机制非常重要,其如何实现的?代码中实现如下: 指向一 ...
- S3C2440上RTC时钟驱动开发实例讲解(转载)
嵌入式Linux之我行,主要讲述和总结了本人在学习嵌入式linux中的每个步骤.一为总结经验,二希望能给想入门嵌入式Linux的朋友提供方便.如有错误之处,谢请指正. 共享资源,欢迎转载:http:/ ...
- hadoop 多表join:Map side join及Reduce side join范例
最近在准备抽取数据的工作.有一个id集合200多M,要从另一个500GB的数据集合中抽取出所有id集合中包含的数据集.id数据集合中每一个行就是一个id的字符串(Reduce side join要在每 ...
- C/C++二维数组的用法
二维数组在存储时按行优先连续存储,数组名是一个二维指针,如 int a[3][2] 中,a 是一个二维指针,而a[0],a[1],a[2]都相当于普通的一位数组的数组名,是一个固定值的指针. 二维数组 ...
- java实现ftp文件的上传与下载
最近在做ftp文件的上传与下载,基于此,整理了一下资料.本来想采用java自带的方法,可是看了一下jdk1.6与1.7的实现方法有点区别,于是采用了Apache下的框架实现的... 1.首先引用3个包 ...