Reactive Streams 1) is the standard/specification for reactive data processing (ie observer, asynchronous processing)
The characteristics are:
It's also known as Observable's reactive dataflow because it is all about observing a stream (flow-controlled components) in which:
This is a push based systems (observer)
A reactive stream process is
The fact that the downstream can be slower than the upstream is taken in the domain model. You can be disconnected if consuming too slow. Examples Twitter streaming API
It's also called reactive functional programming.
The model has 4 interfaces.
A Publisher is a provider of a potentially unbounded number of sequenced elements, publishing them according to the demand received from its Subscriber(s).
A Publisher can serve multiple Subscriber's subscribed dynamically at various points in time.
public interface Publisher<T> {
public void subscribe(Subscriber<? super T> s);
}
A Subscriber - A receiver of messages - arranges that items be requested and processed.
It
public interface Subscriber<T> {
public void onSubscribe(Subscription s);
public void onNext(T t);
public void onError(Throwable t);
public void onComplete();
}
A Subscription represents a link between a Publisher and a Subscriber. It is used to:
public interface Subscription {
public void request(long n);
public void cancel();
}
A Processor combines the capabilities of a Publisher and a Subscriber in a single interface.
public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
}
In response to a call to Publisher.subscribe(Subscriber) the possible invocation sequences for methods on the Subscriber are given by the following protocol:
onSubscribe onNext* (onError | onComplete)?
ie:
This section will show different asynchronous scenarios that are all valid asynchronous streams. They all have their place and each has different tradeoffs including performance and implementation complexity.
Example is made with the following flow
nioSelectorThreadOrigin map(f) filter(p) consumeTo(toNioSelectorOutput)
where:
On this flow, the Subscription.request(n) create a unit of process that must be chained from the destination to the origin. Each implementation can choose to implement it with different scenario
The following scenarios uses:
nioSelectorThreadOrigin | map(f) | filter(p) | consumeTo(toNioSelectorOutput)
-------------- R1 ---- | - R2 - | -- R3 --- | ---------- R4 ----------------
In this example each of the 3 consumers, map, filter and consumeTo asynchronously schedule the work. It could be on the same event loop (trampoline), separate threads, whatever.
nioSelectorThreadOrigin map(f) filter(p) | consumeTo(toNioSelectorOutput)
------------------- R1 ----------------- | ---------- R2 ----------------
Or another implementation could fuse the operations to the final consumer:
nioSelectorThreadOrigin | map(f) filter(p) consumeTo(toNioSelectorOutput)
--------- R1 ---------- | ------------------ R2 -------------------------
Reactive Streams Specification for the JVM define the basic semantics:
Reactive Streams includes:
Starting from Java 9, they have become a part of the JDK in the form of the java.util.concurrent.Flow interfaces or you can get them as java dependencies with the following maven coordinates
https://github.com/reactive-streams/reactive-streams-js/