Presentation is loading. Please wait.

Presentation is loading. Please wait.

Advanced Topics in Concurrency and Reactive Programming: ReactiveX

Similar presentations


Presentation on theme: "Advanced Topics in Concurrency and Reactive Programming: ReactiveX"— Presentation transcript:

1 Advanced Topics in Concurrency and Reactive Programming: ReactiveX
Majeed Kassis

2 ReactiveX Collection of utility functions that facilitate reactive programming. It contains Schedulers which makes threading simple. Operators to transform, combine, manipulate, and work with the sequence of items emitted by Observables In Essense: ReactiveX is a library for composing asynchronous and event-based programs by using observable sequences using functional programming. The stream of data is called Observables, which we receive over time. Instead of gathering them, we respond to each one of the elements in the stream. ReactiveX Is a Polyglot Implementation JavaScript, .Net, Objective-C, Java, etc. We will be talking about RxJava

3 RxJava2 Maven Dependency
<dependency> <groupId>io.reactivex.rxjava2</groupId> <artifactId>rxjava</artifactId> <version>2.1.0</version> </dependency>

4 Observable In ReactiveX an observer subscribes to an Observable.
Then that observer reacts to whatever item or sequence of items the Observable emits. This style allows concurrent operations since it does not block waiting for the Observable to emit its values. Instead, using the Observer pattern, the observer stands ready to react appropriately at whatever future time the Observable does so

5 subscribe(), blockingSubscribe()
Using subscribe function we register (connect) an Observer to listen to an Observable sequence emits. blockingSubscribe() makes the subscription a blocking one, by joining the current thread with the Observer. To solve the issue with limited Java8 Lambdas, subscribe is overloaded to fit all (most) possible combinations. This allows us to implement lambdas for each operation we require by implementing a Consumer/Action interfaces for the specific operation. onNext, onError, onSubscribe → Consumer interface. onComplete → Action interface.

6 subscribe() overloads
13 //Subscribes to an ObservableSource and ignores onNext and onComplete emissions. Disposable subscribe(); // Subscribes to an ObservableSource and provides a callback to handle the items it emits. Disposable subscribe(Consumer<? super T> onNext); // Subscribes to an ObservableSource and provides callbacks to handle the items it emits and any error notification it issues. Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError); // Subscribes to an ObservableSource and provides callbacks to handle the items it emits and any error or completion notification it issues. Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete); Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete, Consumer<? super Disposable> onSubscribe); // Subscribes the given Observer to this ObservableSource instance. void subscribe(Observer<? super T> observer); Using the Disposable object returned the caller can control the Observable, to pause or resume sending items. Changing the Disposable value to true will cause the Observable to pause. Changing the Disposable value to false, will cause the Observable to resume.

7 Observable Types Three kinds of Observables: Hot, Cold, Connectable.
These observables answer the following question: When does an Observable begin emitting its sequence of items? Hot Observable: Begins emitting items as soon as it is created. Any observer who later subscribes to that Observable may start observing the sequence somewhere in the middle. Cold Observable: (default) Waits until an observer subscribes to it before it begins to emit items. Each observer is guaranteed to see the whole sequence from the beginning. Connectable Observable: Begins emitting values once its connect function is executed. Acts as Hot Observable after it begins emitting values.

8 Connectable Observable: using Publish
Using Publish, an ordinary observable is converted to a connectable observable. Publish: convert an ordinary Observable into a connectable Observable

9 General Flow in RxJava Creating an Observable.
Giving that Observable some data to emit. Creating an Observer. Assigning the Observer to an Observable. Giving the Observer tasks to perform whenever it receives an emission from its assigned Observable.

10 RxJava Reactive Types - io.reactivex.*
Flowable: Emits 0 or n items. Terminates with complete or an error. Supports backpressure. Observable: No backpressure support.

11 RxJava Reactive Types - io.reactivex.*
Single: The reactive version of Future. Emits either a single item or an error. onSubscribe(onSuccess | onError) Maybe: The reactive version of an Optional. Succeeds with an item, or no item, or emits an error. onSubscribe(onSuccess | onError | onComplete) Completable: The reactive version of a Runnable. Either completes or emits an error. It never return items, just like Runnable. onSubscribe(onComplete | onError)

12 Creating an Observable: Explicit Implementation
Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> e) throws Exception { //Use onNext to emit each item in the stream e.onNext(1); e.onNext(2); e.onNext(3); e.onNext(4); //Once the Observable has emitted all items in the sequence, call onComplete e.onComplete(); } );

13 Creating an Observable: Lambda Implementation
Observable<Integer> observable = Observable.create(e -> { //Use onNext to emit each item in the stream/ e.onNext(1); e.onNext(2); e.onNext(3); e.onNext(4); //Once the Observable has emitted all items in the sequence, call onComplete e.onComplete(); };

14 Another Observable Example
Observable<Todo> todoObservable = Observable.create(emitter -> { try { List<Todo> todos = getTodos(); //can be from a network, or some threadpool! for (Todo todo : todos) { emitter.onNext(todo); } emitter.onComplete(); } catch (Exception e) { emitter.onError(e); });

15 Single Example Single<List<Todo>> todoSingle = Single.create(emitter -> { try { List<Todo> todos = getTodos(); emitter.onSuccess(todos); } } catch (Exception e) { emitter.onError(e); }); Single will generate a single item. onSuccess emits a single item, and unsubscribes Observers from the Observable.

16 Maybe Example: A05MaybeExample
Maybe<List<Todo>> todoMaybe = Maybe.create(emitter -> { try { List<Todo> todos = getTodos(); if(todos != null && !todos.isEmpty()) { emitter.onSuccess(todos); } else { emitter.onComplete(); } } catch (Exception e) { emitter.onError(e); }); Maybe will generate a single item, then apply a condition on the item. The Observable will emit onSuccess with a single item if the condition is met or emits onComplete if not. Finally it unsubscribes Observers from the Observable, in both cases.

17 Completable – A06 Example
Completable is mainly used when we wish to be notified once some job we wish to do is complete. We do not need it to return anything. In case of success we wish to be notified In case of failure we wish to be notified Completable must be done asynchronously otherwise it voids its purpose. Examples: Updating UI Updating database Saving values into files Sending files over network

18 Creating an Observer Observer<Integer> observer = new Observer<Integer>() { @Override public void onSubscribe(Disposable d) { System.out.println("onSubscribe: "); } public void onNext(Integer value) { System.out.println("onNext: " + value); public void onError(Throwable e) { System.out.println("onError: “ + e.getMessage()); public void onComplete() { System.out.println("onComplete: All Done!"); }; //Create our subscription observable.subscribe(observer); Disposable object is like ‘shouldStop’ object, which contains a Boolean, and two methods: dispose(), and isDisposable(). Once we execute observer.dispose(), we will sever the connection between the Observer and the Observable, which means that the Observer will no longer receive new items from the Observable.

19 More ways to create Observable
Observable.just() Converts any object into an Observable. The Observable will emit the object, and complete. Example: Observable<String> observable = Observable.just("Hello World!"); Observable.from() Converts any Collection of objects into an Observable stream. an array into an Observable using Observable.fromArray a Callable into an Observable using Observable.fromCallable an Iterable into an Observable using Observable.fromIterable

20 Even more ways to create Observables
Observable.range() Converts a range of sequential integers. The first integer rovided is the initial value, and the second is the number of integers to emit Example: Observable<Integer> observable = Observable.range(0, 5); Observable.interval() This operator creates an Observable that emits an infinite sequence of ascending integers, with each emission separated by a time interval. Example: Observable<Long> observable = Observable.interval(1, TimeUnit.SECONDS) Observable.empty() Creates an Observable that emits no items but terminates normally Mainly used for testing purposes. Example: Observable<String> observable = Observable.empty();

21 Schedulers By default, everything is done in the same thread!
an Observable and the chain of operators applied to it to do its work, will notify its observers, on the same thread on which its Subscribe method is called. ObserveOn operator specifies a different Scheduler that the Observable will use to send notifications to its observers. Its location affects the thread on which the Observable will be below its appearance. SubscribeOn specifies a different Scheduler on which the Observable should operate. It does not matter its place in the code!

22 Types of Schedulers Schedulers.computation( )
Uses own threadpool, and used for computational work (not I/O!) Schedulers.from(executor) Uses user specified threadpool. Schedulers.immediate( ) Schedulers.io( ) Used for i/o-bound tasks. Schedulers.newThread( ) Creates a new thread for the task to be ran on. Schedulers.trampoline( ) Queues work on current thread, after the completion of the current work.

23 Using Schedulers Without Subscribe, nothing happens. .subscribe()
All values emitted by Observables reach no Observers. .subscribe() Actions that do something and return void. All done on same thread. .subscribeOn() Which thread to subscribe on the Observable stream. .observeOn() Which thread runs the Observer

24 Example: All in Sync - A00 Example
For example, this Observable operation emits three String objects and maps their lengths: By default everything runs on the same thread! Which means not asynchronous behavior. Each item is generated, emitted, then consumed in a loop.

25 Without subscribeOn() – A01, A02 Examples
public static void main(String[] args) { Observable<String> source = Observable.just("Alpha","Beta","Gamma"); Observable<Integer> lengths = source.map(String::length); lengths.subscribe(l -> System.out.println("Received " + l + " on thread " + Thread.currentThread().getName())); } Output? Received 5 on thread main Received 4 on thread main Flow: The main thread executed the emissions of this Observable It pushed each emission through the map() operator to the Subscriber. Since the main thread becomes occupied with pushing the emissions, the program will not exit until the Observable is done pushing emissions and calls onCompleted().

26 Using subscribeOn() – A04 Example
public static void main(String[] args) { Observable<String> source = Observable.just("Alpha","Beta","Gamma"); Observable<Integer> lengths = source .subscribeOn(Schedulers.computation()) .map(String::length); lengths.blockingSubscribe(l -> System.out.println("Received " + l + " on thread " + Thread.currentThread().getName())); } Output? Received 5 on thread RxComputationThreadPool-1 Received 4 on thread RxComputationThreadPool-1

27 Using observeOn() – A03 Example
public static void main(String[] args) { Observable<Integer> source = Observable.range(1,5); source.map(i -> i * 100) .doOnNext(i -> System.out.println("Emitting " + i + " on thread " + Thread.currentThread().getName())) .observeOn(Schedulers.computation()) .map(i -> i * 10) .subscribe(i -> System.out.println("Received " + i + " on thread " + Thread.currentThread().getName())); sleep(3000); } Emitting 100 on thread main Emitting 200 on thread main Emitting 300 on thread main Emitting 400 on thread main Emitting 500 on thread main Received 1000 on thread RxComputationThreadPool-3 Received 2000 on thread RxComputationThreadPool-3 Received 3000 on thread RxComputationThreadPool-3 Received 4000 on thread RxComputationThreadPool-3 Received 5000 on thread RxComputationThreadPool-3

28 Different Composable Functions in RxJava
Transform: map, flatMap, reduce, scan Filter: take, skip, sample, takeWhile, filter,… Combine: concat, merge, zip, combineLatest, multicast, publish, cache, refCount, .. Concurrency: observeOn, subscribeOn Error Handling: onErrorReturn, onErrorResume ...

29 publish(): Converting a cold to hot stream – A07 Example
By default RxJava Streams are cold streams. Each time an Observer begins observing the stream it will begin from the start. Making streams hot can be done by using publish() function. As a result, the stream will emit the current value regardless of the time the observer begins observing. See code example. One hot stream. First observer begins receiving values from the start Second observer joins in the middle and receives from the current index only

30


Download ppt "Advanced Topics in Concurrency and Reactive Programming: ReactiveX"

Similar presentations


Ads by Google