Rxjava溫故知新(八)------背壓模式

https://github.com/ReactiveX/RxJava/wiki/Backpressure-(2.0)

1.前言

1.在Rxjava1.x中不存在背壓模式
2.在RxJava2.x中產生了了背壓模式

1.什麼是背壓模式

背壓模式主要是爲了解決上游發送大量的事件,下游處理不過來的情況,使用Flowable來操作。相比較Observable多了背壓策略。
背壓涉及到數據緩衝池,緩衝池大小爲128

2.背壓的使用

因爲使用背壓模式就不得不使用到背壓的模式,所以下面根據提供的幾種背壓模式來說明,背壓模式採用Flowable創建被觀察者,
對應的觀察者應該爲Subscriber,也可以使用快捷簡單的Consumer
和前面講到的Observable對比如下

Observable -------> Observer
Flowable   -------> Subscriber

2.1 BackpressureStrategy.ERROR

說明
上游發送大量數據,下游處理不過來(發生了阻塞,常常出現在異步操作裏面),放入緩存池(128大小) ,如果池子滿了,就會拋出異常

例子

 Flowable.create(new FlowableOnSubscribe<String>() {
        @Override
        public void subscribe(FlowableEmitter<String> emitter) throws Exception {
            for (int i = 0; i < 200; i++) {  //
                emitter.onNext("===> " + i);
            }
            emitter.onComplete();
        }
    }, BackpressureStrategy.ERROR)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<String>() {
        @Override
        public void onSubscribe(Subscription s) {
            s.request(200); //請求發射的數據 如果小於上游發射的數據,則還有部分數據不能正常發射則會拋出異常
        }

        @Override
        public void onNext(String s) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i(TAG, "onNext: " + s);
        }

        @Override
        public void onError(Throwable t) {
            Log.i(TAG, "onError: " + t);
        }

        @Override
        public void onComplete() {
            Log.i(TAG, "onComplete: ");
        }
    });

輸出1 (由於在上面我們說明了,緩衝池大小爲128,在此例子中,我們不間斷的發射200條數據,採用異步的方式,下游會休眠1毫秒,這樣就會導致,上游不斷的發射數據,下游處理不過來,會往緩衝池存儲,緩衝池滿了以後,就會拋出異常。)

1572315942.919 I/MainActivity: onNext: ===> 0
1572315942.920 I/MainActivity: onNext: ===> 1
1572315942.921 I/MainActivity: onNext: ===> 2
1572315942.923 I/MainActivity: onNext: ===> 3
1572315942.924 I/MainActivity: onNext: ===> 4
1572315942.925 I/MainActivity: onNext: ===> 5
1572315942.927 I/MainActivity: onNext: ===> 6
1572315942.928 I/MainActivity: onNext: ===> 7
1572315942.929 I/MainActivity: onNext: ===> 8
1572315942.930 I/MainActivity: onNext: ===> 9
1572315942.932 I/MainActivity: onNext: ===> 10
1572315942.933 I/MainActivity: onNext: ===> 11
1572315942.934 I/MainActivity: onError: io.reactivex.exceptions.MissingBackpressureException: create: could not emit value due to lack of requests

案例2 下面我們修改一下上面的數據,再次驗證

Flowable.create(new FlowableOnSubscribe<String>() {
        @Override
        public void subscribe(FlowableEmitter<String> emitter) throws Exception {
            for (int i = 0; i < 200; i++) {
                emitter.onNext("===> " + i);
            }
            emitter.onComplete();
        }
    }, BackpressureStrategy.ERROR)
//                .subscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<String>() {
            @Override
            public void onSubscribe(Subscription s) {
                s.request(200);
            }

            @Override
            public void onNext(String s) {
//                try {
//                    Thread.sleep(1);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
            Log.i(TAG, "onNext: " + s);
        }

        @Override
        public void onError(Throwable t) {
            Log.i(TAG, "onError: " + t);
        }

        @Override
        public void onComplete() {
            Log.i(TAG, "onComplete: ");
        }
    });

這裏我們註釋掉了線程的切換,讓程序在一個線程裏面運行,註釋掉了線程休眠1毫秒的操作,這個時候上游發射的數據,下游能夠及時的處理,不會出現阻塞的情況。輸出結果如下

1572316741.677 I/MainActivity: onNext: ===> 0
1572316741.677 I/MainActivity: onNext: ===> 1
1572316741.677 I/MainActivity: onNext: ===> 2
				(省略...太長了)
1572316741.683 I/MainActivity: onNext: ===> 197
1572316741.683 I/MainActivity: onNext: ===> 198
1572316741.683 I/MainActivity: onNext: ===> 199
1572316741.683 I/MainActivity: onComplete: 

2.2 BackpressureStrategy.BUFFER

說明

上游發送大量數據,下游處理不過來 ,等待下游接收事件處理

例子 (還是採用上面的第一個例子,只是背壓模式改成了Buffer)

	Flowable.create(new FlowableOnSubscribe<String>() {
        @Override
        public void subscribe(FlowableEmitter<String> emitter) throws Exception {
            for (int i = 0; i < 200; i++) {
                emitter.onNext("===> " + i);
            }
            emitter.onComplete();
        }
    }, BackpressureStrategy.BUFFER)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<String>() {
                @Override
                public void onSubscribe(Subscription s) {
                    s.request(200);
                }

                @Override
                public void onNext(String s) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.i(TAG, "onNext: " + s);
                }

                @Override
                public void onError(Throwable t) {
                    Log.i(TAG, "onError: " + t);
                }

                @Override
                public void onComplete() {
                    Log.i(TAG, "onComplete: ");
                }
            });

輸出 (可以看到改成Buffer以後,上游處理不過來的時候會等待下去,直到全部處理完成)

1572317529.486 I/MainActivity: onNext: ===> 0
1572317529.487 I/MainActivity: onNext: ===> 1
1572317529.488 I/MainActivity: onNext: ===> 2
	(部分省略。。。。)
1572317529.770 I/MainActivity: onNext: ===> 195
1572317529.771 I/MainActivity: onNext: ===> 196
1572317529.773 I/MainActivity: onNext: ===> 197
1572317529.774 I/MainActivity: onNext: ===> 198
1572317529.775 I/MainActivity: onNext: ===> 199
1572317529.776 I/MainActivity: onComplete: 

2.3 BackpressureStrategy.DROP(不常用)

說明

上游發送大量數據,下游處理不過來 放入緩存池 ,如果池子滿了,就會把後面的數據丟棄

例子

Flowable.create(new FlowableOnSubscribe<String>() {
        @Override
        public void subscribe(FlowableEmitter<String> emitter) throws Exception {
            for (int i = 0; i < 200; i++) {
                emitter.onNext("===> " + i);
            }
            emitter.onComplete();
        }
    }, BackpressureStrategy.DROP)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<String>() {
                @Override
                public void onSubscribe(Subscription s) {
                    s.request(200);
                }

                @Override
                public void onNext(String s) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.i(TAG, "onNext: " + s);
                }

                @Override
                public void onError(Throwable t) {
                    Log.i(TAG, "onError: " + t);
                }

                @Override
                public void onComplete() {
                    Log.i(TAG, "onComplete: ");
                }
            });

輸出

1572318474.529 I/MainActivity: onNext: ===> 0
1572318474.531 I/MainActivity: onNext: ===> 1
				(省略。。。。)
1572318474.699 I/MainActivity: onNext: ===> 125
1572318474.702 I/MainActivity: onNext: ===> 126
1572318474.703 I/MainActivity: onNext: ===> 127 (緩衝池滿了就會丟棄掉後面的數據)
1572318474.704 I/MainActivity: onComplete: 

2.4 BackpressureStrategy.LATEST(不常用)

說明

註釋說明:Keeps only the latest onNext value, overwriting any previous value if the  downstream can't keep up.
上游發送大量數據,下游處理不過來 ,只存儲128條數據,最後還會發送最後一條數據

例子

Flowable.create(new FlowableOnSubscribe<String>() {
        @Override
        public void subscribe(FlowableEmitter<String> emitter) throws Exception {
            for (int i = 0; i < 150; i++) {
                emitter.onNext("===> " + i);
            }
            emitter.onComplete();
        }
    }, BackpressureStrategy.LATEST)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<String>() {
                @Override
                public void onSubscribe(Subscription s) {
                    s.request(150);
                }

                @Override
                public void onNext(String s) {
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.i(TAG, "onNext: " + s);
                }

                @Override
                public void onError(Throwable t) {
                    Log.i(TAG, "onError: " + t);
                }

                @Override
                public void onComplete() {
                    Log.i(TAG, "onComplete: ");
                }
            });

輸出(可以看到在最後輸出了128條數據以後,最後還發送了一條149的數據,149在發送的數據裏面就是最後一條也是最新的一條數據,也會被打印出來)

1572330316.528 I/MainActivity: onNext: ===> 0
1572330316.540 I/MainActivity: onNext: ===> 1
				(省略。。。。)
1572330317.889 I/MainActivity: onNext: ===> 126
1572330317.900 I/MainActivity: onNext: ===> 127
1572330317.910 I/MainActivity: onNext: ===> 149

3.結尾

//背壓四種模式 (緩存池128)
//1.BackpressureStrategy.ERROR   //上游發送大量數據,下游處理不過來,放入緩存池 ,如果池子滿了,就會拋出異常
//2.BackpressureStrategy.BUFFER  //上游發送大量數據,下游處理不過來 ,等待下游接收事件處理
//3.BackpressureStrategy.DROP(不常用) //上游發送大量數據,下游處理不過來 放入緩存池 ,如果池子滿了,就會把後面的數據丟棄
//4.BackpressureStrategy.LATEST(不常用) //上游發送大量數據,下游處理不過來 ,只存儲128條數據,最後還會發送最後一條數據


通過 Subscription.request(n) 方法,請求發射的數量
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章