web-dev-qa-db-ja.com

RxJava:監視可能なデフォルトスレッド

私は次のコードを持っています:

Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull final ObservableEmitter<String> s) throws Exception {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        s.onNext("1");
                        s.onComplete();
                    }
                });
                thread.setName("background-thread-1");
                thread.start();
            }
        }).map(new Function<String, String>() {
            @Override
            public String apply(@NonNull String s) throws Exception {
                String threadName = Thread.currentThread().getName();
                logger.logDebug("map: thread=" + threadName);
                return "map-" + s;
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {}

            @Override
            public void onNext(String s) {
                String threadName = Thread.currentThread().getName();
                logger.logDebug("onNext: thread=" + threadName + ", value=" + s);
            }

            @Override
            public void onError(Throwable e) {}

            @Override
            public void onComplete() {
                String threadName = Thread.currentThread().getName();
                logger.logDebug("onComplete: thread=" + threadName);
            }
        });

そして、これが出力です:

map: thread=background-thread-1 
onNext: thread=background-thread-1, value=map-1 
onComplete: thread=background-thread-1

重要な詳細:別のスレッド(Androidではsubscribeスレッド)からmainメソッドを呼び出しています。

したがって、Observableクラスは同期的であり、デフォルトで、イベントを発行する同じスレッドですべて(map +サブスクライバーへの通知などの演算子)を実行するように見えます(s.onNext)、 正しい?私は疑問に思います...それは意図された行動ですか、それとも私は何かを誤解しただけですか?実際、少なくともonNextonCompleteのコールバックは、イベントを発行するスレッドではなく、呼び出し元のスレッドで呼び出されると予想していました。この特定のケースでは、実際の呼び出し元のスレッドは重要ではないことを正しく理解していますか?少なくともイベントが非同期で生成される場合。

もう1つの懸念事項-外部ソースからパラメーターとしてObservableを受け取った場合(つまり、自分で生成しない場合)...ユーザーとして、同期か非同期かを確認する方法がなく、 subscribeOnメソッドとobserveOnメソッドを介してコールバックを受信する場所を明示的に指定する必要がありますよね?

ありがとう!

8
fraggjkee

RxJavaは、並行性については非ピニオンです。 observeOn/subscribeOnのような他のメカニズムを使用しない場合、サブスクライブスレッドで値が生成されます。演算子でThreadのような低レベルの構造を使用しないでください。コントラクトが破られる可能性があります。

スレッドを使用しているため、onNextは呼び出し元のスレッド(「background-thread-1」)から呼び出されます。サブスクリプションは呼び出し時に発生します(UIスレッド)。チェーンの下流にあるすべての演算子は、「background-thread-1」-calling-Threadから呼び出されます。サブスクリプションonNextも「background-thread-1」から呼び出されます。

呼び出し元のスレッドにない値を生成する場合は、subscribeOnを使用します。スレッドをメインに戻す場合は、チェーンのどこかでobserveOnを使用します。おそらくそれを購読する前に。

例:

Observable.just(1,2,3) // creation of observable happens on Computational-Threads
            .subscribeOn(Schedulers.computation()) // subscribeOn happens only once in chain. Nearest to source wins
            .map(integer -> integer) // map happens on Computational-Threads
            .observeOn(AndroidSchedulers.mainThread()) // Will switch every onNext to Main-Thread
            .subscribe(integer -> {
                // called from mainThread
            });

ここに良い説明があります。 http://tomstechnicalblog.blogspot.de/2016/02/rxjava-understanding-observeon-and.html

9
Hans Wurst