6. *Future(s) are not enough
• Supporting single (scalar) values,
• Future<T>.get(period, TimeUnit) still blocks
threads,
• Composing is hard - leading to callback hell,
• Complex flows required some kind of FSM,
• Error handling is error-prone :)
6
9. Reactive manifesto v2
Reactive system has to be:
9
Responsive thus react to users demand
Resilient thus react to errors and failure
Elastic thus react to load
Message-driven thus react to events and messages
11. Reactive programming
• Wikipedia says: “Data flows and propagation of
change”,
• I prefer: “programming with asynchronous
(in)finite data sequences”
• Basically pushing data instead of pulling it
11
12. Reactive extensions
• Implement reactive programming paradigm over
(in)finite sequences of data,
• Push data propagation:
• Observer pattern on steroids,
• Declarative (functional) API for composing
sequences,
• Non-opinionated about source of concurrency
(schedulers, virtual time)
12
14. .NET was there first
• Version 1.0 released 17.11.2009,
• Shipped with .NET 4.0 by default,
• Version 2.0 released 15.08.2012,
• With a support for “Portable Library” (.NET 4.5)
• Reactive Extensions for JS released 17.03.2010
14
15. RxJava 1.0.x
• Ported from .NET to JVM by Netflix,
• Stable API release in November 2014,
• After nearly two years of development,
• Targeting Java (and Android), Scala, Groovy,
JRuby, Kotlin and Clojure,
• Last version 1.0.5 released 3 days ago
15
16. Observable<T> vs Iterable<T> vs
Future<T>
16
Scalar value Sequence
Synchronous T Iterable<T>
Asynchronous* Future<T> Observable<T>
* Observable is single-threaded by default
17. Observable is an ordered (serial) data sequence
17
* this is so called marble diagram (source: https://github.com/ReactiveX/RxJava/wiki/How-To-Use-RxJava)
23. Observable<T> functional API
23
Operator class Source type Result type
Anamorphic
aka unfold
T Observable<T>
Bind
aka map
Observable<T1> Observable<T2>
Catamorphic
aka fold or reduce
Observable<T> T
http://en.wikipedia.org/wiki/Anamorphism, http://en.wikipedia.org/wiki/Catamorphism
24. Unfold operatorsaka “how to create observables”
24
Operator Description
Observable.just(T value) Wraps plain value(s) into Observable
Observable.range(int from, int to) Generates range sequence
Observable.timer() Generates time-based sequence
Observable.interval() Generates interval-based sequence
Observable.create(OnSubscribe<T>) Creates observable with delegate (most powerful)
Observable.never() Empty sequence that never completes either way
Observable.empty() Empty sequence that completes right away
Observable.error(Throwable t) Empty sequence that completes with error
26. OnSubscribe<T> contract
• onNext() called from a single thread (synchronisation is not
provided)
• onCompleted() and onError() called exactly once,
• Subscriber.isUnsubscribed() is checked prior to sending any
notification
• setProducer() is used to support reactive-pull back-pressure
26
27. Producer
• Provided to support reactive pull back-pressure,
• Observer can request n elements from producer,
• If n == Long.MAX_VALUE back-pressure is disabled,
• Still hard to use and do it right :(
• But there is some work being done with FSM to
better support back-pressure implementation
27
29. Subscriber<T>
• Basically both Observer<T> and Subscription,
• Used in Operator<T, R> for lifting Observables
into Observables,
• Maintains subscription list
29
30. Operator<T, R>
• Covers “bind” operator class for lifting Observables
• Can preserve state in a scope of chained calls,
• Should maintain subscriptions and unsubscribe requests,
• It’s hard to write it right (composite subscriptions, back-
pressure, cascading unsubscribe requests)
30
35. Schedulers
• Source of concurrency for Observables:
• Observable can use them via observeOn/subscribeOn,
• Schedules unit of work through Workers,
• Workers represent serial execution of work.
• Provides different processing strategies (Event Loop, Thread
Pools, etc),
• Couple provided out-of-the-box plus you can write your own
35
36. Schedulers
36
Name Description
Schedulers.computation()
Schedules computation bound work
(ScheduledExecutorService with pool size = NCPU, LRU
worker select strategy)
Schedulers.immediate() Schedules work on current thread
Schedulers.io()
I/O bound work (ScheduledExecutorService with growing
thread pool)
Schedulers.trampoline() Queues work on the current thread
Schedulers.newThread() Creates new thread for every unit of work
Schedulers.test() Schedules work on scheduler supporting virtual time
Schedulers.from(Executor e) Schedules work to be executed on provided executor
37. (subscribe|observe)On
• Think of them this way:
• subscribeOn - invocation of the subscription,
• observeOn - observing of the notifications
• Thus:
• subscribeOn for background processing and
warm-up
37
40. Subjects
• Subject is a proxy between Observable<T> and
Subscriber<T>
• It can subscribe multiple observables
• And emit items as an observable
• Different Subject types has different properties
40
46. Cold vs hot observables
• Passive sequence is cold:
• Producing notifications when requested
• At rate Observer desires
• Ideal for reactive pull model of back-pressure using Producer.request(n)
• Active sequence is hot:
• Producing notifications regardless of subscriptions:
• Immediately when it is created
• At rate Observer sometimes cannot handle,
• Ideal for flow control strategies like buffering, windowing, throttling,
onBackpressure*
46
47. Cold vs hot examples
47
Cold Hot
Asynchronous requests
(Observable.from)
UI events (mouse clicks,
movements)
Created with OnSubscribe<T> Timer events
Subscriptions to queues Push pub/sub (broadcasts)
50. Design considerations
• Reactive Extensions are not a silver-bullet for dealing with concurrency:
• Threading/synchronization concerns does not go away,
• You can still block your threads (dead-lock),
• Simple flows on top of RX and static sequences yields significant overhead,
• Choosing right operators flow is a challenge,
• You should avoid shared-state if possible (immutability FTW),
• Debugging is quite hard (but there is “plugins” mechanism),
• Understanding and using back-pressure well is harder :)
50