Advanced Topics in Concurrency and Reactive Programming: ReactiveX

Slides:



Advertisements
Similar presentations
Chapter 17 Failures and exceptions. This chapter discusses n Failure. n The meaning of system failure. n Causes of failure. n Handling failure. n Exception.
Advertisements

Reactive Extension to .NET
CS220 Software Development Lecture: Multi-threading A. O’Riordan, 2009.
Threads II. Review A thread is a single flow of control through a program Java is multithreaded—several threads may be executing “simultaneously” If you.
50.003: Elements of Software Construction Week 5 Basics of Threads.
Copyright © 2003 ProsoftTraining. All rights reserved. Sun Certified Java Programmer Exam Preparation Guide.
Reactive Extensions Ye olde introduction and walk-through, with plenty o’ code.
© 2004, D. J. Foreman 2-1 Concurrency, Processes and Threads.
Java Threads. What is a Thread? A thread can be loosely defined as a separate stream of execution that takes place simultaneously with and independently.
1 Web Based Programming Section 8 James King 12 August 2003.
Saeed Ghanbartehrani Summer 2015 Lecture Notes #5: Programming Structures IE 212: Computational Methods for Industrial Engineering.
Multithreading in Java Sameer Singh Chauhan Lecturer, I. T. Dept., SVIT, Vasad.
Introduction to Threads Session 01 Java Simplified / Session 14 / 2 of 28 Objectives Define a thread Define multithreading List benefits of multithreading.
Threads in Java1 Concurrency Synchronizing threads, thread pools, etc.
Multithreaded programming  Java provides built-in support for multithreaded programming. A multithreaded program contains two or more parts that can run.
 In the java programming language, a keyword is one of 50 reserved words which have a predefined meaning in the language; because of this,
 Control Flow statements ◦ Selection statements ◦ Iteration statements ◦ Jump statements.
Threads b A thread is a flow of control in a program. b The Java Virtual Machine allows an application to have multiple threads of execution running concurrently.
Concurrency in Java MD. ANISUR RAHMAN. slide 2 Concurrency  Multiprogramming  Single processor runs several programs at the same time  Each program.
Concurrent Programming in Java Based on Notes by J. Johns (based on Java in a Nutshell, Learning Java) Also Java Tutorial, Concurrent Programming in Java.
 It is a pure oops language and a high level language.  It was developed at sun microsystems by James Gosling.
Multithreading The objectives of this chapter are:
Recipes in RxJava for Android
RxJava and SWT: Out with Events, in with FRP
Information and Computer Sciences University of Hawaii, Manoa
Java Exceptions a quick review….
Multithreading / Concurrency
EECE 310: Software Engineering
Multi Threading.
Advanced Topics in Concurrency and Reactive Programming: Asynchronous Programming Majeed Kassis.
Advanced Topics in Concurrency and Reactive Programming: The Observable Contract Majeed Kassis.
Concurrency, Processes and Threads
Testing and Exceptions
Functional Programming with Java
Multithreading.
Fundamental Error Handling
Multithreading 2 Lec 24.
Advanced Topics in Concurrency and Reactive Programming
Multithreading.
Multithreaded Programming
Android Topics UI Thread and Limited processing resources
Android Topics Asynchronous Callsbacks
Stacks Abstract Data Types (ADTs) Stacks
Lecture 11 Objectives Learn what an exception is.
9. Threads SE2811 Software Component Design
CMSC 202 Exceptions 2nd Lecture.
Threads in Java James Brucker.
Multithreading in java.
Using threads for long running tasks.
Threads and Multithreading
Introduction to Programming
CSC 143 Java Errors and Exceptions.
Exceptions.
9. Threads SE2811 Software Component Design
Concurrency, Processes and Threads
Rx Java intro Vaidas Kriščeliūnas.
Loops CGS3416 Spring 2019 Lecture 7.
Advanced Topics in Functional and Reactive Programming: Reactive Streams Majeed Kassis.
CMSC 202 Exceptions 2nd Lecture.
Exceptions.
CMSC 202 Exceptions.
Exception Handling.
Java Programming: From Problem Analysis to Program Design, 4e
Multithreading The objectives of this chapter are:
Software Engineering and Architecture
„Lambda expressions, Optional”
CMSC 202 Threads.
9. Threads SE2811 Software Component Design
More concurrency issues
Java Chapter 3 (Estifanos Tilahun Mihret--Tech with Estif)
Presentation transcript:

Advanced Topics in Concurrency and Reactive Programming: ReactiveX Majeed Kassis

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 https://github.com/ReactiveX/RxJava http://reactivex.io/

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

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

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.

subscribe() overloads 1 2 3 4 5 6 7 8 9 10 11 12 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.

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.

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

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.

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

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)

Creating an Observable: Explicit Implementation 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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(); } );

Creating an Observable: Lambda Implementation 1 2 3 4 5 6 7 8 9 10 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(); };

Another Observable Example 1 2 3 4 5 6 7 8 9 10 11 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); });

Single Example 1 2 3 4 5 6 7 8 9 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.

Maybe Example: A05MaybeExample 1 2 3 4 5 6 7 8 9 10 11 12 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.

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

Creating an Observer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 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.

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

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();

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!

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.

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

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.

Without subscribeOn() – A01, A02 Examples 1 2 3 4 5 6 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().

Using subscribeOn() – A04 Example 1 2 3 4 5 6789 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

Using observeOn() – A03 Example 1 2 3 4 5 6 7 8 9 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

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 ... http://rxmarbles.com/

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