RxJava2.0

其中有一篇博客写的很精彩戳这里,这个非常简洁
还有一篇精彩博文戳这里,这个解释的非常通透

一、背景

无论是java8的CompletableFuture还是RxJava都是基于观察者模式的。只不过Rxjava更强大,有更好的错误处理、中断机制、完成状态

二、创建

  • Observable ( 被观察者 ) / Observer ( 观察者 )
  • Flowable (被观察者)/ Subscriber (观察者) 【支持回压】
package com.hfview;


import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import lombok.extern.slf4j.Slf4j;

/**
 * 观察者和被观察者创建
 *
 * @author: zhw
 * @since: 2019/3/15 09:36
 */
@Slf4j
public class RxJavaDemo1 {

    public static void main(String[] args) {

        //创建被观察者---方式1
        Observable<String> switcher1 = Observable.create(emitter->{
            log.debug("Observable emit 1");
            emitter.onNext("1");

            log.debug("Observable emit 2");
            emitter.onNext("2");

            log.debug("Observable emit 3");
            emitter.onNext("3");

            log.debug("Observable emit 4");
            emitter.onNext("4");

            log.debug("Observable emit onComplete ");
            emitter.onComplete();
        });

        //创建被观察者---方式2
        //Observable<String> switcher2 = Observable.just("on","off","on","on");

        //创建被观察者---方式3
        //String [] kk={"On","Off","On","On"};
        //Observable<String> switcher3 =Observable.fromArray(kk);


        //创建观察者
        switcher1.subscribe(new Observer<String>() {

            private Disposable disposable;

            @Override
            public void onSubscribe(Disposable d) {
                log.debug("     观察者onSubscribe");
                disposable = d;
            }

            @Override
            public void onNext(String s) {
                log.debug("     观察者onNext:"+s);
                if(s.equals("2")){
                    disposable.dispose();
                }
            }

            @Override
            public void onError(Throwable e) {
                log.error("     观察者onError",e);
            }

            @Override
            public void onComplete() {
                log.info("      观察者onComplete");
            }
        });

    }

}

  1. 第一种方式是最基本的,其实后面也是基于它的
  2. just方式
  3. fromArray方式

1.1 没有观察者,被观察者是不会生产事件的

假如没有 switcher1.subscribe() 这个操作,观察者不会调用各种释放Next
注意这里有个误解,应该是观察者订阅被观察者,但是为了链式调用的方便,就搞成被观察者订阅观察者了。

1.2 Disposable 方式

如果在观察者onNext方法中调用Disposable 的dispose方法,那么就可以终止获取,但是被观察者仍然继续生产,只是这个观察者不接受了
比如上面观察者中onNext方法只会打印到 观察者onNext:1 观察者onNext:2 剩下的却不打印了。

1.3 观察者onError

如果观察者在onNext中发生异常,那么会在onError自动捕获改异常

二、数据转换处理和线程切换

package com.hfview;


import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;

/**
 * 数据转换和线程切换
 *
 * @author: zhw
 * @since: 2019/3/15 09:36
 */
@Slf4j
public class RxJavaDemo2 {

    public static void main(String[] args) throws Exception{

        CountDownLatch countDownLatch = new CountDownLatch(1);
        long start = System.currentTimeMillis();

        //创建被观察者---方式2
        Observable
                .just("11011","21011","31011","41011")
                //.subscribeOn(Schedulers.newThread())//被观察者线程切换
                //.observeOn(Schedulers.io())
                    .map(s->{
                        log.debug("map操作当前线程为:"+Thread.currentThread().getName());
                        return convert(s);//转换功能
                    })
                    /*.flatMap(new Function<String, ObservableSource<String>>() {
                        @Override
                        public ObservableSource<String> apply(String s) throws Exception {
                            return Observable.fromArray(s.split("0"));
                        }
                    })*/
                    .observeOn(Schedulers.computation())
                .subscribe(new Observer<String>() {
                    private Disposable disposable;

                    @Override
                    public void onSubscribe(Disposable d) {
                        log.debug("     观察者调用onSubscribe:"+Thread.currentThread().getName());
                        disposable = d;
                    }

                    @Override
                    public void onNext(String s) {
                        sleep(2000);
                        log.debug("     观察者接受数据onNext:"+s+"  "+Thread.currentThread().getName());
                    }

                    @Override
                    public void onError(Throwable e) {
                        log.error("     观察者调用onError"+Thread.currentThread().getName(),e);
                    }

                    @Override
                    public void onComplete() {
                        log.info("      观察者调用onComplete"+Thread.currentThread().getName());
                        countDownLatch.countDown();
                    }
                });

        countDownLatch.await();
        long end = System.currentTimeMillis();
        log.debug("主线程结束了,耗时:"+(end-start));
    }

    /**
     * 模拟耗时操作
     * @param s
     * @return
     */
    public static String convert(String s){
        //sleep(2000);
        return s+"1";
    }

    public static void sleep(int n){
        try {
            Thread.sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

如果清楚java中Stream中的流处理,那么这里他它差不多

2.1 Map

public final <R> Observable<R> map(Function<? super T, ? extends R> mapper)

在函数式编成中也有这个接口Function,他基本就是负责转换,他需要一个入参? super T 和一个出参 ? extends R

.map(s->{
       log.debug("map操作当前线程为:"+Thread.currentThread().getName());
       return convert(s);//转换功能
  })
 public static String convert(String s){
        return s+"1";
  }

比如上面就是完成将当前字符串+“1”。

2.2 filter

public final Observable<T> filter(Predicate<? super T> predicate);

和函数式接口Predicate一样一个入参,然后返回boolean。true就保留,false就剔除

2.3 线程切换

  • 简单地说,subscribeOn() 指定的就是发射事件的线程,observerOn 指定的就是订阅者接收事件的线程。
  • 多次指定发射事件的线程只有第一次指定的有效,也就是说多次调用 subscribeOn() 只有第一次的有效,其余的会被忽略。
  • 但多次指定订阅者接收线程是可以的,也就是说每调用一次 observerOn(),下游的线程就会切换一次。

关于Schedulers的解释
在这里插入图片描述

三、支持回压的模式

3.1 回压

回压或者背压:主要是处理如果被观察者产生时间过快,而观察者来不及处理,导致堆积,导致OOM的事情。

下面是一个例子:

package com.hfview;


import io.reactivex.Flowable;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;

import java.util.concurrent.CountDownLatch;

/**
 * 支持回压的Flowable
 *
 * @author: zhw
 * @since: 2019/3/15 09:36
 */
@Slf4j
public class RxJavaDemo3 {

    public static void main(String[] args) throws Exception{

        CountDownLatch countDownLatch = new CountDownLatch(1);
        long start = System.currentTimeMillis();

        final int length  = 100000;
        String[] arr = new String[length];
        for(int i=0;i<length;i++){
            arr[i] = (i+1)+"";
        }

        //创建被观察者---方式2
        Flowable.fromArray(arr)
                .subscribe(new Subscriber<String>() {
                    private Subscription subscription;
                    private int count = 0;

                    @Override
                    public void onSubscribe(Subscription s) {
                        log.debug("     观察者调用onSubscribe"+Thread.currentThread().getName());
                        subscription = s;
                        s.request(10);
                    }

                    @Override
                    public void onNext(String s) {
                        count++;
                        //sleep(200);
                        log.debug("     观察者接受数据onNext:"+s+"  "+Thread.currentThread().getName());

                        if(count!=0&&count%10==0){
                            log.debug("观察者再次请求数据10条,当前已经处理了:"+count+"条");
                            subscription.request(10);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        log.error("     观察者调用onError"+Thread.currentThread().getName(),e);
                    }

                    @Override
                    public void onComplete() {
                        log.info("      观察者调用onComplete"+Thread.currentThread().getName());
                        countDownLatch.countDown();
                    }
                });

        countDownLatch.await();
        long end = System.currentTimeMillis();
        log.debug("主线程结束了,耗时:"+(end-start));
    }

    /**
     * 模拟耗时操作
     * @param s
     * @return
     */
    public static String convert(String s){
        return s+"1";
    }

    public static void sleep(int n){
        try {
            Thread.sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

用法基本和Observable。
区别:

  • 观察者onSubscribe中会传递一个类Subscription,他有两个方法public void request(long n)public void cancel(),意思也很明显,调用request(10),意思我只需要10个事件处理,被观察者收到命令后就产生10个。 cancel就是取消。

四、一个简单例子

package com.hfview;


import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;

/**
 * //TODO 写注释
 *
 * @author: zhw
 * @since: 2019/3/15 15:54
 */
@Slf4j
public class RxJavaDemo4 {

    public static void main(String[] args) throws Exception{

        long start =  System.currentTimeMillis();
        CountDownLatch countDownLatch = new CountDownLatch(1);

        Observable observable1 = Observable.fromCallable(new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.debug("被观察者生成字符串1");
                sleep(3000);
                return "1";
            }
        }).subscribeOn(Schedulers.newThread());

        Observable observable2 = Observable.fromCallable(new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.debug("被观察者生成字符串2");
                sleep(3000);
                return "2";
            }
        }).subscribeOn(Schedulers.newThread());;

        Observable observable3 = Observable.fromCallable(new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.debug("被观察者生成字符串3");
                sleep(3000);
                return "3";
            }
        }).subscribeOn(Schedulers.newThread());;


        //Observable<String> unionObservable = observable1.concatWith(observable2).concatWith(observable3);
        Observable<String> unionObservable = observable1.mergeWith(observable2).mergeWith(observable3);


        unionObservable
                .subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {

            }

            @Override
            public void onNext(String s) {
               log.debug("      观察者获取数据:"+s);
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onComplete() {
                countDownLatch.countDown();
            }
        });


        countDownLatch.await();
        long end = System.currentTimeMillis();
        log.debug("主线程结束了,耗时:"+(end-start));

    }


    public static void sleep(int n){
        try {
            Thread.sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

一共三个事件各自需要3S,现在使用响应式编成,最后只需要3S就完成操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值