Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RxJava, RxJava 2, Reactor: State of the art of ...

RxJava, RxJava 2, Reactor: State of the art of Reactive Streams on the JVM

RxJava is used on Android or in backend side thanks to Hystrix. RxJava 2 is now available and will be able to use the path build by the previous version. Pivotal promote Reactor that will be available in Spring Boot 2.

What is the differences between each of these implementations of the Reactive Streams? Why chose RxJava 2 over Reactor or over RxJava?

This conference talk will focus on the history of each implementation then will compare APIs, performances and use cases of these Reactive Streams.

- DevDays Vilinus - may 2018

David

May 23, 2018
Tweet

More Decks by David

Other Decks in Programming

Transcript

  1. Future Future<?> future1 = /* ... */
 Future<?> future2 =

    /* ... */
 Future<?> future3 = /* ... */
 Future<?> future4 = /* ... */
 Future<?> future5 = /* ... */ Optimal Orchestration ?
  2. Callback RemoteService service = buildRemoteService();
 service.getUser(id -> {
 service.getData(id, data

    -> {
 service.getSomething(data, whut -> { service.neverEndingCallBack(whut, () -> { }); });
 });
 }); Callback Hell
  3. RxJava is not compatible 
 with Reactive Streams (You’ll have

    to use an adapter: RxJavaReactiveStreams) https://github.com/ReactiveX/RxJavaReactiveStreams
  4. onNext * ( onError | onComplete ) 
 onNext *

    ( onError | onCompleted ) RxJava Reactive Streams
  5. onNext * ( onError | onComplete ) 
 onNext *

    ( onError | onCompleted ) RxJava Reactive Streams Different name
  6. A P I t o h a n d l

    e e v e n t s synchronously or asynchronously through a flow of events
  7. remoteApi.people(1).flatMap(luke -> { 
 Observable<String> vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle

    -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable<String> starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println);
  8. remoteApi.people(1).flatMap(luke -> { 
 Observable<String> vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle

    -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable<String> starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Push of the result
  9. remoteApi.people(1).flatMap(luke -> { 
 Observable<String> vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle

    -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable<String> starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Get Luke’s vehicles Get Luke’s starships
  10. remoteApi.people(1).flatMap(luke -> { 
 Observable<String> vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle

    -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable<String> starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Merge of two flows
  11. remoteApi.people(1).flatMap(luke -> { 
 Observable<String> vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle

    -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable<String> starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Really execute the code
  12. remoteApi.people(1).flatMap(luke -> { 
 Observable<String> vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle

    -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable<String> starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Flow of events
  13. remoteApi.people(1).flatMap(luke -> { 
 Observable<String> vehicles = Observable.from(luke.getVehiclesIds())
 .flatMap(remoteApi::vehicle)
 .map(vehicle

    -> luke.getName() + " can drive " + vehicle.getName());
 
 Observable<String> starships = Observable.from(luke.getStarshipsIds())
 .flatMap(remoteApi::starship)
 .map(starship -> luke.getName() + " can fly with " + starship.getName());
 
 return Observable.merge(vehicles, starships); 
 }).subscribe(System.out::println); Flow of events Flow of events
  14. Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) 


    .observeOn(Schedulers.io()) 
 .switchMap(evt -> remoteApi.getData())
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe();
  15. Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) //

    Observable<Event>
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData())
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Listen for clicks
  16. Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) //

    Observable<Event>
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData())
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Execution context switch
  17. Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) //

    Observable<Event>
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData()) // Observable<Data>
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Asynchronous call to a web service
  18. Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) //

    Observable<Event>
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData()) // Observable<Data>
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Execution context switch
  19. Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) //

    Observable<Event>
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData()) // Observable<Data>
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Update on the UI
  20. Button btn = new Button();
 btn.setText("Click Me");
 
 JavaFx.fromClick(btn) //

    Observable<Event>
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData()) // Observable<Data>
 .observeOn(javaFx()) 
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Flow of events
  21. Creation of 
 Reactive Extensions Creation of RxJava Active Participation

    Resumption of 
 RxJava & RxJava 2 Creation of Reactor Work on Reactor
  22. RxJava Contrat Backpressure Observable [N] Yes Single [1] No Completable

    [0] No Added afterward Web service call Background process
  23. Listen a websocket, for each received command, compose a response

    by calling 3 different webservices, then execute 2 jobs sequentially ?
  24. Listen a websocket, for each received command, compose a response

    by calling 3 different webservices, then execute 2 jobs sequentially ?
  25. Listen a websocket, for each received command, compose a response

    by calling 3 different webservices, then execute 2 jobs sequentially ?
  26. Listen a websocket, for each received command, compose a response

    by calling 3 different webservices, then execute 2 jobs sequentially ?
  27. websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())


    .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Listen a websocket Observable
  28. websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())


    .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Webservices composition Single
  29. websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())


    .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Completable 2 jobs executions
  30. websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())


    .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Listen a websocket Observable Webservices composition Single Completable 2 jobs executions
  31. RxJava 2 Contrat Backpressure Observable [N] No Single [1] No

    Completable [0] No Maybe [0|1] No New! Close to Java 8 Optional
  32. acceptedIntent
 .filter(intent -> !intent.getBooleanExtra("UpdatePhoneMode", false))
 .concatMap(intent -> approximatedEngine.detectCurrentPlace())
 .doOnNext(score ->

    Log.info(TAG, "Scan completed with result " + score))
 .concatMap(this::detectSleepMode)
 .concatMap((score) -> isNewPlace(score.getScore().getPlace()).map(p -> score))
 .doOnNext((p) -> Log.info(TAG, "Current place found is : " + p))
 .subscribe()
  33. acceptedIntent
 .filter(intent -> !intent.getBooleanExtra("UpdatePhoneMode", false)) .onBackpressureDrop()
 .concatMap(intent -> approximatedEngine.detectCurrentPlace())
 .doOnNext(score

    -> Log.info(TAG, "Scan completed with result " + score))
 .onBackpressureDrop() .concatMap(this::detectSleepMode)
 .onBackpressureDrop()
 .concatMap((score) -> isNewPlace(score.getScore().getPlace()).map(p -> score))
 .doOnNext((p) -> Log.info(TAG, "Current place found is : " + p))
 .subscribe() Added while I panicked
  34. RxJava 2 Contrat Backpressure Observable [N] No Single [1] No

    Completable [0] No Maybe [0|1] No New! Close to Java 8 Optional
  35. RxJava 2 Contrat Backpressure Observable [N] No Single [1] No

    Completable [0] No Maybe [0|1] No Flowable [N] Yes New! Observable with 
 back pressure Close to Java 8 Optional
  36. Observable → less than 1000 events → User interface management

    → To be used instead of Java 8 Streams Flowable → more than 10 000 events → Control the data flow → Network stream with flow management
  37. You can use a library which use RxJava 2 in

    your Reactor project (and vice versa)
  38. all amb ambArray ambWith any as awaitOnSubscribe blockFirst blockFirstMillis blockLast

    blockLastMillis blockingFirst blockingForEach blockingIterable blockingLast blockingLatest blockingMostRecent blockingNext blockingSingle blockingSubscribe buffer bufferMillis bufferSize bufferTimeout bufferTimeoutMillis bufferUntil bufferWhile cache cacheWithInitialCapacity cancelOn cast checkpoint collect collectInto collectList collectMap collectMultimap collectSortedList combineLatest combineLatestDelayError compose concat concatArray concatArrayDelayError concatArrayEager concatDelayError concatEager concatMap concatMapDelayError concatMapEager concatMapEagerDelayError concatMapIterable concatWith contains count create debounce defaultIfEmpty defer delay delayElements delayElementsMillis delayMillis delaySubscription delaySubscriptionMillis dematerialize distinct distinctUntilChanged doAfterNext doAfterTerminate doFinally doOnCancel doOnComplete doOnEach doOnError doOnLifecycle doOnNext doOnRequest doOnSubscribe doOnTerminate elapsed elementAt elementAtOrError empty equals error filter first firstElement firstEmitting firstEmittingWith firstOrError flatMap flatMapCompletable flatMapIterable flatMapMaybe flatMapSequential flatMapSingle forEach forEachWhile from fromArray fromCallable fromFuture fromIterable fromPublisher fromStream generate getClass getPrefetch groupBy groupJoin handle hasElement hasElements hashCode hide ignoreElements interval intervalMillis intervalRange isEmpty join just last lastElement lastOrError lift limitRate log map mapError materialize merge mergeArray mergeArrayDelayError mergeDelayError mergeSequential mergeWith never next notify notifyAll observeOn ofType onBackpressureBuffer onBackpressureDrop onBackpressureError onBackpressureLatest onErrorResumeNext onErrorResumeWith onErrorReturn onErrorReturnItem onExceptionResumeNext onTerminateDetach parallel publish publishNext publishOn range rangeLong rebatchRequests reduce reduceWith repeat repeatUntil repeatWhen replay replayMillis retry retryUntil retryWhen safeSubscribe sample sampleFirst sampleFirstMillis sampleMillis sampleTimeout scan scanWith sequenceEqual serialize share single singleElement singleOrEmpty singleOrError skip skipLast skipMillis skipUntil skipUntilOther skipWhile sort sorted startWith startWithArray strict subscribe subscribeOn subscribeWith switchIfEmpty switchMap switchMapDelayError switchOnError switchOnNext switchOnNextDelayError take takeLast takeMillis takeUntil takeUntilOther takeWhile test then thenEmpty thenMany throttleFirst throttleLast throttleWithTimeout timeInterval timeout timeoutMillis timer timestamp to toFuture toIterable toList toMap toMultimap toObservable toSortedList toStream toString transform unsafeCreate unsubscribeOn using wait window windowMillis windowTimeout windowTimeoutMillis windowUntil windowWhile withLatestFrom zip zipArray zipIterable zipWith zipWithIterable
  39. RxJava RxJava 2 Reactor flatMap flatMap flatMap Emit Noe, one

    or more events amb amb firstEmitting Emit events from the first emitting stream … … … … debounce debounce N/A Ignore events during a time laps
  40. RxJava RxJava 2 Reactor flatMap flatMap flatMap Emit Noe, one

    or more events amb amb firstEmitting Emit events from the first emitting stream … … … … debounce debounce N/A Ignore events during a time laps Renamed
  41. https://github.com/ReactiveX/RxJava/wiki/Implementing-custom-operators-(draft) writing operators is hard when one writes an operator,

    the Observable protocol, unsubscription, backpressure and concurrency have to be taken into account and adhered to the letter
  42. RxJava
 RxJava 2 Reactor Flowable.just Flux.just Emitting existing value Flowable.defer

    Flux.defer Lazy emitting Flowable.fromCallable Mono.fromCallable Lazy emitting, computed from a method call Flowable.create Flux.create Manual emitting Flowable.using Flux.using Resource management Flowable.fromPublisher Flux.from Using a Publisher (Reactive Streams) Flowable.generate Flux.generate Using a value generator
  43. RxJava
 RxJava 2 Reactor Flowable.just Flux.just Emitting existing value Flowable.defer

    Flux.defer Lazy emitting Flowable.fromCallable Mono.fromCallable Lazy emitting, computed from a method call Flowable.create Flux.create Manual emitting Flowable.using Flux.using Resource management Flowable.fromPublisher Flux.from Using a Publisher (Reactive Streams) Flowable.generate Flux.generate Using a value generator
  44. RxJava
 RxJava 2 Reactor Flowable.just Flux.just Emitting existing value Flowable.defer

    Flux.defer Lazy emitting Flowable.fromCallable Mono.fromCallable Lazy emitting, computed from a method call Flowable.create Flux.create Manual emitting Flowable.using Flux.using Resource management Flowable.fromPublisher Flux.from Using a Publisher (Reactive Streams) Flowable.generate Flux.generate Using a value generator
  45. RxJava
 RxJava 2 Reactor Flowable.just Flux.just Emitting existing value Flowable.defer

    Flux.defer Lazy emitting Flowable.fromCallable Mono.fromCallable Lazy emitting, computed from a method call Flowable.create Flux.create Manual emitting Flowable.using Flux.using Resource management Flowable.fromPublisher Flux.from Using a Publisher (Reactive Streams) Flowable.generate Flux.generate Using a value generator
  46. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 CountDownLatch latch = new CountDownLatch(1);
 AtomicReference<String> result = new AtomicReference<>();
 this.connection.subscribe((message, pattern) -> {
 result.set(message.toString());
 latch.countDown();
 }, TOPIC_NAME);
 latch.await();
 return result.get();
 } }
  47. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 CountDownLatch latch = new CountDownLatch(1);
 AtomicReference<String> result = new AtomicReference<>();
 this.connection.subscribe((message, pattern) -> {
 result.set(message.toString());
 latch.countDown();
 }, TOPIC_NAME);
 latch.await();
 return result.get();
 } }
  48. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 CountDownLatch latch = new CountDownLatch(1);
 AtomicReference<String> result = new AtomicReference<>();
 this.connection.subscribe((message, pattern) -> {
 result.set(message.toString());
 latch.countDown();
 }, TOPIC_NAME);
 latch.await();
 return result.get();
 } }
  49. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 CountDownLatch latch = new CountDownLatch(1);
 AtomicReference<String> result = new AtomicReference<>();
 this.connection.subscribe((message, pattern) -> {
 result.set(message.toString());
 latch.countDown();
 }, TOPIC_NAME);
 latch.await();
 return result.get();
 } } Code for synchronisation Code for synchronisation
  50. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 
 String result = Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> {
 sub.onNext(message.toString());
 sub.onComplete();
 }, TOPIC_NAME);
 }, BackpressureStrategy.BUFFER)
 .blockingFirst();
 return result;
 } }
  51. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private String redis() throws InterruptedException {
 
 String result = Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> {
 sub.onNext(message.toString());
 sub.onComplete();
 }, TOPIC_NAME);
 }, BackpressureStrategy.BUFFER)
 .blockingFirst();
 return result;
 } } Wrapping Synchronisation Reactive Contract
  52. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private DeferredResult<String> redis() throws InterruptedException {
 
 DeferredResult<String> result = new DeferredResult<>(10_000l);
 
 Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> {
 sub.onNext(message.toString());
 sub.onComplete();
 }, TOPIC_NAME);
 }, BackpressureStrategy.BUFFER)
 .subscribe(result::setResult);
 
 return result;
 }
  53. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis")
 private DeferredResult<String> redis() throws InterruptedException {
 
 DeferredResult<String> result = new DeferredResult<>(10_000l);
 
 Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> {
 sub.onNext(message.toString());
 sub.onComplete();
 }, TOPIC_NAME);
 }, BackpressureStrategy.BUFFER)
 .subscribe(result::setResult);
 
 return result;
 } Lazy result Use of DeferredResult
  54. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
 private Flux<String> redis() throws InterruptedException {
 
 Flowable<String> rxjava = Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> sub.onNext(message.toString()), TOPIC_NAME);
 }, BackpressureStrategy.BUFFER);
 
 return Flux.defer(() -> rxjava);
 } }
  55. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
 private Flux<String> redis() throws InterruptedException {
 
 Flowable<String> rxjava = Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> sub.onNext(message.toString()), TOPIC_NAME);
 }, BackpressureStrategy.BUFFER);
 
 return Flux.defer(() -> rxjava);
 } } RxJava 2 → Flux Flux → SSE Return a Flux
  56. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
 private Publisher<String> redis() throws InterruptedException {
 return Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> sub.onNext(message.toString()), TOPIC_NAME);
 }, BackpressureStrategy.BUFFER);
 
 }
  57. @RestController
 public class HelloController {
 
 private static final byte[]

    TOPIC_NAME = "topic".getBytes();
 
 @RequestMapping(value = "/redis", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
 private Publisher<String> redis() throws InterruptedException {
 return Flowable.create(sub -> {
 this.connection.subscribe((message, pattern) -> sub.onNext(message.toString()), TOPIC_NAME);
 }, BackpressureStrategy.BUFFER);
 
 } Publisher
  58. RxJava RxJava 2 Reactor Description io() io() elastic() Thread pool

    which grow up if needed computation() computation() parallel() Limited thread pool single() single() single() Pool of 1 thread immediate() immediate() Execute the task immediately trampoline() trampoline() Queue the current task
  59. RxJava RxJava 2 Reactor Description io() io() elastic() Thread pool

    which grow up if needed computation() computation() parallel() Limited thread pool single() single() single() Pool of 1 thread immediate() immediate() Execute the task immediately trampoline() trampoline() Queue the current task
  60. RxJava RxJava 2 Reactor Description io() io() elastic() Thread pool

    which grow up if needed computation() computation() parallel() Limited thread pool single() single() single() Pool of 1 thread immediate() immediate() Execute the task immediately trampoline() trampoline() Queue the current task
  61. for (int x = 0; x < 10_000; x++) {


    
 Observable.interval(10, TimeUnit.MILLISECONDS)
 .takeWhile(i -> take.get())
 .flatMap(i -> Observable.range(1, 100))
 .subscribe();
 }
  62. RxJava RxJava 2 Reactor Retrofit Yes Yes No RxAndroid Yes

    Yes No Realm Yes No No Hystrix Yes No No Couchbase Yes No No MongoDB Yes No No Spring Data 2.0 Yes No Yes Reactor IPC No No Yes WebFlux No Yes Yes Android Spring
  63. RxJava RxJava 2 Reactor Retrofit Yes Yes No RxAndroid Yes

    Yes No Realm Yes No No Hystrix Yes No No Couchbase Yes No No MongoDB Yes No No Spring Data 2.0 Yes No Yes Reactor IPC No No Yes WebFlux No Yes Yes Android Spring
  64. RxJava RxJava 2 Reactor Retrofit Yes Yes No RxAndroid Yes

    Yes No Realm Yes No No Hystrix Yes No No Couchbase Yes No No MongoDB Yes No No Spring Data 2.0 Yes No Yes Reactor IPC No No Yes WebFlux No Yes Yes Android Spring
  65. RxJava RxJava 2 Reactor Retrofit Yes Yes No RxAndroid Yes

    Yes No Realm Yes No No Hystrix Yes No No Couchbase Yes No No MongoDB Yes No No Spring Data 2.0 Yes No Yes Reactor IPC No No Yes WebFlux No Yes Yes Android Spring
  66. Thanks for your attention We stay in touch? [email protected] @dwursteisen

    http://blog.soat.fr Post your question on sli.do ( #K100 )