Flowable之Backpressure

rxjava 2.0开始多了一个Flowable,乍一看和Observable的方法差不多。但是当我调用create创建一个observable的时候发现多了一个差数

public static <T> Flowable<T> create(FlowableOnSubscribe<T> source, BackpressureStrategy mode) {
        return RxJavaPlugins.onAssembly(new FlowableCreate<T>(source, mode));
    }

BackpressureStrategy,背压策略 ,在异步环境下,当数据处理不够快时通过通知上游来控制流速的一种策略

public enum BackpressureStrategy {
    /**
     * OnNext events are written without any buffering or dropping.
     * Downstream has to deal with any overflow.
     * <p>Useful when one applies one of the custom-parameter onBackpressureXXX operators.
     */
    MISSING,
    /**
     * Signals a MissingBackpressureException in case the downstream can't keep up.
     */
    ERROR,
    /**
     * Buffers <em>all</em> onNext values until the downstream consumes it.
     */
    BUFFER,
    /**
     * Drops the most recent onNext value if the downstream can't keep up.
     */
    DROP,
    /**
     * Keeps only the latest onNext value, overwriting any previous value if the
     * downstream can't keep up.
     */
    LATEST
}

目前有这么多种背压策略。来看一下FlowableCreate是怎么根据背压策略来控制流速的。

首先创建一个Flowable查看输出值

Flowable
    .create(new FlowableOnSubscribe<Integer>() {
        @Override
        public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                emitter.onNext(i);
                Thread.sleep(20);
            }
    
            emitter.onComplete();
        }
        //随便定义一个策略
    },BackpressureStrategy.MISSING)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Consumer<Integer>() {
        @Override
        public void accept(Integer value) throws Exception {
            //print value
        }
    });

如上的代码如果是Observable的话是打印0-max的,在Flowable下是怎么样呢。

在这里我是先查看源码在猜测输出值,看一下FlowableCreate.subscribeActual是怎么执行的。

public void subscribeActual(Subscriber<? super T> t) {
    BaseEmitter<T> emitter;

    switch (backpressure) {
    case MISSING: {
        emitter = new MissingEmitter<T>(t);
        break;
    }
    case ERROR: {
        emitter = new ErrorAsyncEmitter<T>(t);
        break;
    }
    case DROP: {
        emitter = new DropAsyncEmitter<T>(t);
        break;
    }
    case LATEST: {
        emitter = new LatestAsyncEmitter<T>(t);
        break;
    }
    default: {
        emitter = new BufferAsyncEmitter<T>(t, bufferSize());
        break;
    }
    }

    t.onSubscribe(emitter);
    try {
        source.subscribe(emitter);
    } catch (Throwable ex) {
        Exceptions.throwIfFatal(ex);
        emitter.onError(ex);
    }
}
MISSING

根据不同的策略创建不同的FlowableEmitter。接下来看一下MissingEmitter。

static final class MissingEmitter<T> extends BaseEmitter<T> {

    private static final long serialVersionUID = 3776720187248809713L;

    MissingEmitter(Subscriber<? super T> downstream) {
        super(downstream);
    }

    @Override
    public void onNext(T t) {
        if (isCancelled()) {
            return;
        }

        if (t != null) {
            downstream.onNext(t);
        } else {
            onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
            return;
        }

        for (;;) {
            long r = get();
            if (r == 0L || compareAndSet(r, r - 1)) {
                return;
            }
        }
    }

}

MissingEmitter继承了BaseEmitter,

abstract static class BaseEmitter<T>
    extends AtomicLong
    implements FlowableEmitter<T>, Subscription {
    private static final long serialVersionUID = 7326289992464377023L;

    final Subscriber<? super T> downstream;

    //维持管理当前FlowableEmitters是否关闭订阅
    final SequentialDisposable serial;

    BaseEmitter(Subscriber<? super T> downstream) {
        this.downstream = downstream;
        this.serial = new SequentialDisposable();
    }

    @Override
    public void onComplete() {
        complete();
    }

    //没有关闭订阅 交给下游处理onComplete
    protected void complete() {
        if (isCancelled()) {
            return;
        }
        try {
            downstream.onComplete();
        } finally {
            serial.dispose();
        }
    }

    @Override
    public final void onError(Throwable e) {
        if (!tryOnError(e)) {
            RxJavaPlugins.onError(e);
        }
    }

    @Override
    public boolean tryOnError(Throwable e) {
        return error(e);
    }

    //没有关闭订阅 交给下游处理onError
    protected boolean error(Throwable e) {
        if (e == null) {
            e = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources.");
        }
        if (isCancelled()) {
            return false;
        }
        try {
            downstream.onError(e);
        } finally {
            serial.dispose();
        }
        return true;
    }

    //关闭订阅
    @Override
    public final void cancel() {
        serial.dispose();
        onUnsubscribed();
    }

    void onUnsubscribed() {
        // default is no-op
    }

    @Override
    public final boolean isCancelled() {
        return serial.isDisposed();
    }

    @Override
    public final void request(long n) {
        //判断n是否大于0
        if (SubscriptionHelper.validate(n)) {
            BackpressureHelper.add(this, n);
            onRequested();
        }
    }

    void onRequested() {
        // default is no-op
    }

    @Override
    public final void setDisposable(Disposable d) {
        serial.update(d);
    }

    @Override
    public final void setCancellable(Cancellable c) {
        setDisposable(new CancellableDisposable(c));
    }

    @Override
    public final long requested() {
        return get();
    }

}

我们发现BaseEmitter实现了Subscription接口,里面有个request(int),就是他来实现流速的控制,表示可以处理多少个流。多次request调用是会累加的。

这里看一下request方法的具体实现:

由于BaseEmitter继承自AtomicLong,request流量的大小设置本质就是通过设置AtomicLong的值来实现。
首先调用SubscriptionHelper.validate(n)来判断是否大于0

是的话

public static long add(AtomicLong requested, long n) {
    for (;;) {
        //获取当前值
        long r = requested.get();
        if (r == Long.MAX_VALUE) {
            return Long.MAX_VALUE;
        }
        //相加
        long u = addCap(r, n);
        //把相加的值赋值进去
        if (requested.compareAndSet(r, u)) {
            return r;
        }
    }
}

AtomicLong的值表示当前下游可以处理多少onNext输出。后面每当通知下游调用完一次onNext 就会调用BackpressureHelper.produced(this, 1);减1

BaseEmitter已经帮我实现了onError 和onComplete,所以他的继承类就只需要实现onNext

下面就看MissingEmitter具体是怎么实现的

static final class MissingEmitter<T> extends BaseEmitter<T> {

        private static final long serialVersionUID = 3776720187248809713L;

        MissingEmitter(Subscriber<? super T> downstream) {
            super(downstream);
        }

        @Override
        public void onNext(T t) {
            //是否取消
            if (isCancelled()) {
                return;
            }

            //不为空就输出
            if (t != null) {
                downstream.onNext(t);
            } else {
                onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
                return;
            }
        }

    }

由上可知BackpressureStrategy.MISSING模式类似Observable 直接全部打印,所以上面的例子是打印从0-MAx。

ERROR

ErrorAsyncEmitter继承自NoOverflowBaseAsyncEmitter

static final class ErrorAsyncEmitter<T> extends NoOverflowBaseAsyncEmitter<T> {

    private static final long serialVersionUID = 338953216916120960L;

    ErrorAsyncEmitter(Subscriber<? super T> downstream) {
        super(downstream);
    }

    @Override
    void onOverflow() {
        onError(new MissingBackpressureException("create: could not emit value due to lack of requests"));
    }

}

abstract static class NoOverflowBaseAsyncEmitter<T> extends BaseEmitter<T> {

    private static final long serialVersionUID = 4127754106204442833L;

    NoOverflowBaseAsyncEmitter(Subscriber<? super T> downstream) {
        super(downstream);
    }

    @Override
    public final void onNext(T t) {
        //是否取消订阅
        if (isCancelled()) {
            return;
        }

        if (t == null) {
            onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
            return;
        }

        //查看当前可处理的流量数量,是否允许下游处理
        if (get() != 0) {
            downstream.onNext(t);
            //可处理的数量减1
            BackpressureHelper.produced(this, 1);
        } else {
            //不允许 回调ErrorAsyncEmitter的onOverflow,抛出错误
            onOverflow();
        }
    }

    abstract void onOverflow();
}

可知ErrorAsyncEmitter是:当上游发送的数据大于下游可处理的数量时 就会抛出错误。
当初把代码改成下面这样

Flowable
    .create(new FlowableOnSubscribe<Integer>() {
        @Override
        public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                emitter.onNext(i);
                Thread.sleep(20);
            }
    
            emitter.onComplete();
        }
        //随便定义一个策略
    },BackpressureStrategy.MISSING)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new FlowableSubscriber<Integer>() {
        @Override
        public void onSubscribe(Subscription s) {
            s.request(5);
        }
        @Override
        public void onNext(Integer value){
            //print value
        }

    });

上面的代码会在打印五次之后抛出错误。

DROP

DropAsyncEmitter和ErrorAsyncEmitter一样继承于NoOverflowBaseAsyncEmitter

static final class DropAsyncEmitter<T> extends NoOverflowBaseAsyncEmitter<T> {

    private static final long serialVersionUID = 8360058422307496563L;

    DropAsyncEmitter(Subscriber<? super T> downstream) {
        super(downstream);
    }

    @Override
    void onOverflow() {
        // nothing to do
    }

}

但是他出错的时候不抛出错误,所以上游继续发送 但是下游没有接收到。

LATEST

LatestAsyncEmitter 是将上游最新的一个值保存起来,每次有新的next都会替换旧的值保存。

static final class LatestAsyncEmitter<T> extends BaseEmitter<T> {

    private static final long serialVersionUID = 4023437720691792495L;

    final AtomicReference<T> queue;

    Throwable error;
    volatile boolean done;

    final AtomicInteger wip;

    LatestAsyncEmitter(Subscriber<? super T> downstream) {
        super(downstream);
        this.queue = new AtomicReference<T>();
        this.wip = new AtomicInteger();
    }

    @Override
    public void onNext(T t) {
        if (done || isCancelled()) {
            return;
        }

        if (t == null) {
            onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
            return;
        }
        
        //每次有新的输出 保存起来
        queue.set(t);
        
        //
        drain();
    }
    
     void drain() {
        //drain()方法只能有一个在运行
        if (wip.getAndIncrement() != 0) {
            return;
        }

        int missed = 1;
        //下游 比如FlowableSubscriber
        final Subscriber<? super T> a = downstream;
        //上游最新的值(FlowableEmitter.onNext(value)方法执行的值的)
        final AtomicReference<T> q = queue;

        for (;;) {
            //获取当前下游可执行的流量数量,通过request(count)方法增加
            long r = get();
            long e = 0L;
            
            //下游可以接收
            while (e != r) {
                //是否取消订阅
                if (isCancelled()) {
                    q.lazySet(null);
                    return;
                }
                
                //没有执行onComplete,为false
                boolean d = done;
                
                //取出最新值,并且把变量设置为null
                T o = q.getAndSet(null);

                boolean empty = o == null;

                if (d && empty) {
                    Throwable ex = error;
                    if (ex != null) {
                        error(ex);
                    } else {
                        complete();
                    }
                    return;
                }

                //最新值为null 说明数据已经被取出 跳出while循环
                if (empty) {
                    break;
                }
                
                //调用下游的onNext
                a.onNext(o);
                
            
                e++;
            }

            //当前调用下游执行的次数 == 下游可执行的数量
            if (e == r) {
                if (isCancelled()) {
                    q.lazySet(null);
                    return;
                }

                boolean d = done;

                boolean empty = q.get() == null;

                if (d && empty) {
                    Throwable ex = error;
                    if (ex != null) {
                        error(ex);
                    } else {
                        complete();
                    }
                    return;
                }
            }

            //如果当前有调用下游执行,就要减掉下游可执行数量
            if (e != 0) {
                BackpressureHelper.produced(this, e);
            }

            //跳出for循环
            missed = wip.addAndGet(-missed);
            if (missed == 0) {
                break;
            }
        }
    }
    
    ...
}

由此可知LatestAsyncEmitter主要思想就是 上游不断执行 ,在上游执行的那一段时间,如果下游不调用Subscription.request()获取,就永远没有收到onNext回调。

当上游执行完之后 会保持最后一个值,这时调用Subscription.request()也能获取到最后一个值


Subscription mSubscription;

Flowable
    .create(new FlowableOnSubscribe<Integer>() {
        @Override
        public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
            for (int i = 0; i < 5; i++) {
                emitter.onNext(i);
                Thread.sleep(20);
            }

            emitter.onComplete();
        }
    }, BackpressureStrategy.MISSING)
    .subscribeOn(Schedulers.io())
    .subscribe(new FlowableSubscriber<Integer>() {
        @Override
        public void onSubscribe(Subscription s) {
            mSubscription = s;
        }
        @Override
        public void onNext(Integer value){
            //print value
        }

    });

因此当几秒钟之后我调用mSubscription.request(5),仍然能在onNext获取到值"4".

BUFFER

BufferAsyncEmitter的代码结构类似LatestAsyncEmitter,唯一的不同是LatestAsyncEmitter只保存上游最后一个值,BufferAsyncEmitter是使用一个队列保存上游的所有输出。

mSubscription.request的时候是从队列获取。

因此下面的代码当我多次调用mSubscription.request(5)获取的时候
第一次是 0-4 第二次是5-9 第三次是10-14 …


Subscription mSubscription;

Flowable
    .create(new FlowableOnSubscribe<Integer>() {
        @Override
        public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                emitter.onNext(i);
                Thread.sleep(20);
            }

            emitter.onComplete();
        }
    }, BackpressureStrategy.MISSING)
    .subscribeOn(Schedulers.io())
    .subscribe(new FlowableSubscriber<Integer>() {
        @Override
        public void onSubscribe(Subscription s) {
            mSubscription = s;
        }
        @Override
        public void onNext(Integer value){
            //print value
        }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值