简体   繁体   中英

Call multiple synchronous tasks asynchronously using RxJava

I have an async task represented by Futures executing in a separate threadpool that I want to join using RxJava. The "old" way of doing it using Java 5 constructs would be something like this (omitting collecting the results):

final Future<Response> future1 = wsClient.callAsync();
final Future<Response> future2 = wsClient.callAsync();
final Future<Response> future3 = wsClient.callAsync();
final Future<Response> future4 = wsClient.callAsync();

future1.get();
future2.get();
future3.get();
future4.get();

This would block my current thread until all futures are completed, but the calls would be in parallell and the whole operation would only take the time equal to the longest call.

I want to do the same using RxJava, but I'm a bit noob when it comes to how to model it correctly.

I've tried the following, and it seems to work:

Observable.from(Arrays.asList(1,2,3,4))
            .flatMap(n -> Observable.from(wsClient.callAsync(), Schedulers.io()))
            .toList()
            .toBlocking()
            .single();

The problem with this approach is that I introduce the Schedulers.io threadpool which causes unnecessary thread switching as I'm already blocking the current thread (using toBlocking()). Is there any way I can model the Rx flow to execute the tasks in parallel, and block until all has been completed?

You should use zip function. For example like this:

Observable.zip(
        Observable.from(wsClient.callAsync(), Schedulers.io()),
        Observable.from(wsClient.callAsync(), Schedulers.io()),
        Observable.from(wsClient.callAsync(), Schedulers.io()),
        Observable.from(wsClient.callAsync(), Schedulers.io()),
        (response1, response2, response3, response4) -> {
            // This is a zipping function...
            // You'll end up here when you've got all responses
            // Do what you want with them and return a combined result
            // ...
            return null; //combined result instead of null
        })
        .subscribe(combinedResult -> {
            // Use the combined result
        });

Observable.zip can also work with an Iterable so you can wrap your Observable.from(wsClient.callAsync(), Schedulers.io()); around with one (that returns 4 of those).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM