编写不易,转载请注明(http://shihlei.iteye.com/blog/2428152)!
一 概述
阅读Hystrix的源码过程,看到很多RxJava的使用,本文对其中一些重要的方法进行总结,为之后Hystrix的讲解做铺垫。
如果对应响应式编程,RxJava不是很了解,可以阅读《响应式编程 RxJava》做个简单的入门。
版本:
io.reactivex.rxjava2 rxjava 2.1.14
二 Observable 操作符
1) defer操作符:
(1)概述
Observable用于封装数据,defer提供懒绑定,直到有订阅时才创建Observable,即冷 Observable;
注:
(a)冷热问题
热Observable:创建后马上执行,生成可观察事件。但观察者注册完后,可能从中间消费事件,造成一定量事件无法观察到。
冷Observable:一直等待,直到有观察者订阅他才开始发送数据,因此观察者可以确保收到整个数据序列。
(b)使用时通过回调传入一个已有Observable,defer()进行包装
(2)demo
package x.rx.rxjava.demo.func;
import io.reactivex.Observable;
/**
* DeferDemo
*
* Observable用于封装数据,defer提供懒绑定,直到有订阅时才创建Observable,即冷 Observable;
*
* 注:
* (a)冷热问题
* 热Observable:创建后马上执行,生成可观察事件。但观察者注册完后,可能从中间消费事件,造成一定量事件无法观察到。
* 冷Observable:一直等待,直到有观察者订阅他才开始发送数据,因此观察者可以确保收到整个数据序列。
*
* (b)使用时通过回调传入一个已有Observable,defer()进行包装
*
* @author shilei
*/
public class DeferDemo {
public static void main(String[] args) {
new DeferDemo().run();
}
private void run() {
System.out.println("do hot observable :");
doHotObservable();
System.out.println("do cold observable : ");
doColdObservable();
}
/**
* 热Observable:创建后马上执行,生成可观察事件。但观察者注册完后,可能从中间消费事件,造成一定量事件无法观察到。
*
* 注:这里通过just模拟
*/
private void doHotObservable() {
Content content = new Content("before");
Observable observable = Observable.just(content.data);
content.data = "after";
//这里输出"befere" ,因为 通过just创建时已经绑定 "before" 的引用,用于保持数据"原生性"很有用
observable.subscribe(result -> System.out.println(result));
}
/**
* 冷Observable:一直等待,直到有观察者订阅他才开始发送数据,因此观察者可以确保收到整个数据序列。
*
* 注:defer 包装一个Observable实现
*/
private void doColdObservable() {
Content content = new Content("before");
Observable observable = Observable.defer(() -> Observable.just(content.data));
content.data = "after";
//这里输出"after" ,延迟绑定,直到subscribe()调用时,才调用获取 content.data;用于保证数据"最新性"很有用
observable.subscribe(result -> System.out.println(result));
}
static class Content {
private String data;
Content(String data) {
this.data = data;
}
@Override
public String toString() {
return "Content{" +
"data='" + data + '\'' +
'}';
}
}
}
(3)结果
do hot observable : before do cold observable : after
分析:
hot observable:生成observable时已经绑定了”before“,所以即使修改content.data=after 对观察者是不可见的。
cold observable(defer):延迟绑定,修改content.data=after 观察者看到的就是”after“,对于订阅到最新数据非常有用。
2)lift操作符:
(1)概述
方法负责将一个Observable转换成另一个Observable,转换方式通过Operator提供。
注:
lift()方法是在一个已有Observable上调用,可以用于Observable封装数据变换。
(2)demo
package x.rx.rxjava.demo.func;
import io.reactivex.Observable;
import io.reactivex.ObservableOperator;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
/**
* LiftDemo:
*
* 概述
* 方法负责将一个Observable转换成另一个Observable,转换方式通过Operator提供。
* 注:
* lift()方法是在一个已有Observable上调用,可以用于Observable封装数据变换。
*
* @author shilei
*/
public class LiftDemo {
public static void main(String[] args) {
new LiftDemo().run();
}
private void run() {
Observable stringObservable = Observable.just("1");
Observable integerObservable = stringObservable.lift(new ObservableOperator() {
@Override
public Observer super String> apply(Observer super Integer> child) throws Exception {
return new Observer() {
@Override
public void onSubscribe(Disposable d) {
child.onSubscribe(d);
}
@Override
public void onNext(String s) {
child.onNext(Integer.valueOf(s));
}
@Override
public void onError(Throwable e) {
child.onError(e);
}
@Override
public void onComplete() {
child.onComplete();
}
};
}
});
integerObservable.subscribe(new Consumer() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("value : " + integer);
}
});
}
}
(3)结果
value : 1
三 线程调度:Scheduler
1)概述
异步执行任务代码:observable.observeOn(Schedulers.newThread()).subscribeOn(Schedulers.newThread())
RxJava实现异步的主要结构,核心三大:
(1)Scheduler:调度器,用于调度一个Worker执行任务,核心方法:Worker createWorker();
(2)Scheduler.Worker:执行线程任务,核心方法:schedule(@NonNull Runnable run)
(3)Schedulers:静态工厂,返回Scheduler 实例,2.x主要有如下几种:
-
-
- TRAMPOLINE:当前线程单线程执行,任务先进先出,一般用于“测试”目的
- SINGLE: 共享单线程异步执行,任务先出执行
- NEW_THREAD:每一个任务一个新的后台线程执行的调度器实例
- COMPUTATION:用于执行计算型任务,使用固定大小的线程池,线程数=cpu 核数
- IO:用于执行IO密集型任务,使用大小动态变化的线程池
-
2)demo
package x.rx.rxjava.demo.scheduler;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import io.reactivex.Scheduler;
import io.reactivex.schedulers.Schedulers;
/**
* SchedulerDemo
*
* 异步执行任务代码:observable.observeOn(Schedulers.newThread()).subscribeOn(Schedulers.newThread())
*
* RxJava实现异步的主要结构,核心三大:
* (1)Scheduler:调度器,用于调度一个Worker执行任务
* 核心方法:Worker createWorker();
*
* (2)Scheduler.Worker:执行线程任务
* 核心方法:schedule(@NonNull Runnable run)
*
* (3)Schedulers:静态工厂,返回Scheduler 实例,2.x主要有如下几种:
*
* TRAMPOLINE:当前线程执行,任务进度队列,先进先出执行
* SINGLE: 拥有一个共享线程执行,任务进度队列,先进先出执行
* NEW_THREAD:每一个任务一个新的后台线程执行的调度器实例
* COMPUTATION:用于执行计算型任务,使用线程池执行,线程数=cpu 核数
* IO:用于执行IO密集型任务,使用线程池执行。
*
* @author shilei
*/
public class SchedulerDemo {
public static void main(String[] args) throws Exception {
System.out.println("当前线程id : " + Thread.currentThread().getId());
new SchedulerDemo().run();
// 等待线程执行结束
TimeUnit.SECONDS.sleep(10);
}
private void run() {
Map schedulers = new LinkedHashMap<>();
schedulers.put("trampoline1", Schedulers.trampoline());
schedulers.put("trampoline2", Schedulers.trampoline());
schedulers.put("single1", Schedulers.single());
schedulers.put("single2", Schedulers.single());
schedulers.put("newThread1", Schedulers.newThread());
schedulers.put("newThread2", Schedulers.newThread());
schedulers.put("computation1", Schedulers.computation());
schedulers.put("computation2", Schedulers.computation());
for (Map.Entry entry : schedulers.entrySet()) {
String type = entry.getKey();
Scheduler scheduler = entry.getValue();
doWork(type, scheduler);
}
}
private void doWork(String info, Scheduler scheduler) {
Scheduler.Worker worker = scheduler.createWorker();
Runnable job = () -> {
System.out.print("类型:" + info);
System.out.println(" , 线程id:" + Thread.currentThread().getId() + " do job! ");
};
worker.schedule(job);
}
}
3)结果
当前线程id : 1 类型:trampoline1 , 线程id:1 do job! 类型:trampoline2 , 线程id:1 do job! 类型:single1 , 线程id:12 do job! 类型:single2 , 线程id:12 do job! 类型:newThread1 , 线程id:13 do job! 类型:newThread2 , 线程id:14 do job! 类型:computation1 , 线程id:15 do job! 类型:computation2 , 线程id:16 do job!
四 解除订阅,中断任务:Disposable
1)概述
用于Observer控制执行过程中解除订阅,典型场景:
(1)业务逻辑:最多处理n个事件,剩下的忽略
(2)超时,解除事件等待:如hystrix的超时熔断
2)Demo
(1)Disposable
用于主动解除订阅,核心方法 dispose();
注:
如果任务异步执行且阻塞时,调用dispose() 会中断阻塞。
如果任务正在执行非阻塞状态,则不会中断,会一直执行完,退出。
package x.rx.rxjava.demo.observer;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
/**
* 异步执解绑定阻塞执行查看
*
* Disposable
* 用于主动解除订阅,核心方法 dispose();
* 注:
* 如果任务异步执行且阻塞时,调用dispose() 会中断阻塞。
* 如果任务正在执行非阻塞状态,则不会中断,会一直执行完,退出。
*
* @author shilei0907
*/
public class DisposableDemo {
public static void main(String[] args) throws Exception {
new DisposableDemo().run();
// 等待线程执行结束
TimeUnit.SECONDS.sleep(10);
}
private void run() throws Exception {
Observable observable = getObservable();
Disposable disposable = observable.observeOn(Schedulers.newThread())
.subscribeOn(Schedulers.newThread())
.subscribe(result -> {
System.out.println("result : " + result);
}, e -> {
e.printStackTrace();
});
//等待启动
TimeUnit.SECONDS.sleep(1L);
// 取消任务
disposable.dispose();
System.out.println("all Finish !");
}
private Observable getObservable() {
Observable observable = Observable.create(emitter -> {
System.out.println(Thread.currentThread().getId() + " start ! ");
try {
TimeUnit.SECONDS.sleep(5);
} catch (Throwable t) {
t.printStackTrace();
}
System.out.println(Thread.currentThread().getId() + " finish ! ");
});
//延迟执行
return Observable.defer(() -> observable);
}
}
结果:
12 start ! all Finish ! 12 finish ! java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at java.lang.Thread.sleep(Thread.java:340) at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386) at x.rx.rxjava.demo.observer.DisposableDemo.lambda$getObservable$2(DisposableDemo.java:57) at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40) at io.reactivex.Observable.subscribe(Observable.java:12051) at io.reactivex.internal.operators.observable.ObservableDefer.subscribeActual(ObservableDefer.java:39) at io.reactivex.Observable.subscribe(Observable.java:12051) at io.reactivex.internal.operators.observable.ObservableObserveOn.subscribeActual(ObservableObserveOn.java:45) at io.reactivex.Observable.subscribe(Observable.java:12051) at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96) at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:579) at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66) at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
(2) CompositeDisposable
用于添加一组Disposable,快速解除订阅,清理资源时很有用。
核心方法:
add(): 添加到组中
clear(): 快速解除所有订阅,中断所有添的“被观察者”正在执行的任务。
package x.rx.rxjava.demo.observer;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
/**
* CompositeDisposableDemo
*
* 用于添加一组Disposable,快速解除订阅,清理资源时很有用。
*
* 核心方法:
* add(): 添加到组中
* clear(): 快速解除所有订阅,中断所有添的“被观察者”正在执行的任务。
*
* @author shilei0907
* @version 1.0, 2018/8/6
*/
public class CompositeDisposableDemo {
public static void main(String[] args) {
new CompositeDisposableDemo().run();
}
private void run() {
CompositeDisposable compositeDisposable = new CompositeDisposable();
Observable.just("message").subscribe(new Observer() {
@Override
public void onSubscribe(Disposable d) {
//添加待管理的订阅
compositeDisposable.add(d);
}
@Override
public void onNext(String s) {
System.out.println("receive : " + s);
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("onComplete");
}
});
// 清理绑定关系
compositeDisposable.clear();
}
}