簡體   English   中英

RxJava與多個訂閱者和事件的並發性

[英]RxJava concurrency with multiple subscribers and events

我正在尋找一種方法將多個訂閱者附加到RxJava Observable流,每個訂閱者異步處理發出的事件。

我首先嘗試使用.flatMap(),但這似乎不適用於任何后續訂閱者。 所有訂閱者都在同一個線程上處理事件。

.flatMap(s -> Observable.just(s).subscribeOn(Schedulers.newThread()))

最終工作的是通過每次創建一個新的Observable來消耗新線程中的每個事件:

Observable.from(Arrays.asList(new String[]{"1", "2", "3"}))
            .subscribe(j -> {
                Observable.just(j)
                        .subscribeOn(Schedulers.newThread())
                        .subscribe(i -> {
                            try {
                                Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println("s1=>" + Thread.currentThread().getName() + "=>" + i);
                        });
            });

輸出:

s1=>RxNewThreadScheduler-1=>1
s1=>RxNewThreadScheduler-2=>2
s1=>RxNewThreadScheduler-3=>3

最終結果是多個訂閱者:

ConnectableObservable<String> e = Observable.from(Arrays.asList(new String[]{"1", "2", "3"}))
            .publish();

    e.subscribe(j -> {
        Observable.just(j)
                .subscribeOn(Schedulers.newThread())
                .subscribe(i -> {
                    try {
                        Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    System.out.println("s1=>" + Thread.currentThread().getName() + "=>" + i);
                });
    });

    e.subscribe(j -> {
        Observable.just(j)
                .subscribeOn(Schedulers.newThread())
                .subscribe(i -> {
                    try {
                        Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    System.out.println("s2=>" + Thread.currentThread().getName() + "=>" + i);
                });
    });

    e.connect();

輸出:

s2=>RxNewThreadScheduler-4=>2
s1=>RxNewThreadScheduler-1=>1
s1=>RxNewThreadScheduler-3=>2
s2=>RxNewThreadScheduler-6=>3
s2=>RxNewThreadScheduler-2=>1
s1=>RxNewThreadScheduler-5=>3

然而,這看起來有點笨重。 有更優雅的解決方案還是RxJava不是一個很好的用例呢?

使用.flatMap(s -> Observable.just(s).observeOn(Schedulers.newThread())....)

如果我正確地理解了rx-contract,那么你正試圖做一些事情,這是違背它的。

讓我們來看看合同

RxJava Observable的契約是事件(onNext(),onCompleted(),onEr ror())永遠不會同時發出。 換句話說,單個Observable流必須始終序列化並且是線程安全的。 只要排放不是並發的,每個事件都可以從不同的線程發出。 這意味着沒有 onNext()的交叉同時執行 如果仍然在一個線程上執行onNext(),則另一個線程無法再次開始調用它(交錯)。 --Tomasz Nurkiewicz在RxJava的反應式編程中

在我看來,你試圖通過在外部訂閱中使用嵌套訂閱來破解合同。 對訂戶的onNext調用不再被序列化。

為什么不將“async”-workload從訂閱者移動到flatMap-operator並訂閱新的observable:

    ConnectableObservable<String> stringObservable = Observable.from(Arrays.asList(new String[]{"1", "2", "3"}))
            .flatMap(s -> {
                return Observable.just(s).subscribeOn(Schedulers.computation());
            })
            .publish();

    stringObservable
            .flatMap(s -> {
                // do More asyncStuff depending on subscription
                return Observable.just(s).subscribeOn(Schedulers.newThread());
            })
            .subscribe(s -> {
                // use result here
            });

    stringObservable
            .subscribe(s -> {
                // use immediate result here.
            });

    stringObservable.connect();

flatMap沿doOnNextObservable里面flatMap將導致相同的輸出你的。

onNext()總是以順序方式調用,因此在flatMap之后使用doOnNext也不適合你。 由於在最終subscribe寫入操作的相同原因在您的情況下不起作用。

以下代碼使用RxJava2編寫。 在RxJava的第1版中,您必須在Thread.sleep周圍添加try-catch塊。

ConnectableObservable<String> e = Observable.just("1", "2", "3").publish();

e.flatMap(
      s -> Observable.just(s)
          .subscribeOn(Schedulers.newThread())
          .doOnNext(i -> {  // <<<<<<
              Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
              System.out.println("s1=>" + Thread.currentThread().getName() + "=>" + i);
          }))
  .subscribe();

e.flatMap(
      s -> Observable.just(s)
          .subscribeOn(Schedulers.newThread())
          .doOnNext(i -> {  // <<<<<<
              Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
              System.out.println("s2=>" + Thread.currentThread().getName() + "=>" + i);
          }))
  .subscribe();

e.connect();

您可以使用Flowable和parallel實現它:

        Flowable.fromIterable(Arrays.asList("1", "2", "3"))
                .parallel(3)
                .runOn(Schedulers.newThread())
                .map(item -> {
                    try {
                        Thread.sleep(ThreadLocalRandom.current().nextInt(100, 500));
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    System.out.println("s1=>" + Thread.currentThread().getName() + "=>" + item);

                    return Completable.complete();
                })
        .sequential().subscribe();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM