Reactive Streams
Table of Contents
- Reactive Streams
- Table of Contents
- Reactive Streams Workflow
- Operators and Transformations
- JDK9 java.util.concurrent.Flow
- Ref.
Is a set of interfaces and rules that define a standard for asynchronous stream processing with non-blocking backpressure in Java. It was developed to address challenges in handling asynchronous and potentially unbounded streams of data, ensuring that data producers (publishers) don’t overwhelm data consumers (subscribers) and lead to resource exhaustion.
Core interfaces
-
Publisher
Represents a source of data that emits items to subscribers. Publishers emit items one by one in response to subscriber requests.
import org.reactivestreams.Subscriber; public interface Publisher<T> { void subscribe(Subscriber<? super T> subscriber); }Publishers emit three types of signals:
onNext,onError, andonComplete:onNext: represents a regular data itemonError: indicates an error conditiononComplete: signals the end of the stream
-
Subscriber
Represents a consumer of data emitted by a publisher. Subscribers signal demand for items (or signals) and receive them asynchronously.
import org.reactivestreams.Subscription; public interface Subscriber<T> { void onSubscribe(Subscription subscription); void onNext(T item); void onError(Throwable throwable); void onComplete(); }A
Subscriberrequests a certain number of items from the Publisher (request(n)) and processes them as they arrive.Subscribers provide methods for handling each type of signal:
onNextfor processing data itemsonErrorfor handling errorsonCompletefor handling the completion of the stream
-
Subscription
Represents the connection between a subscriber and a publisher. It allows subscribers to request items and cancel their subscription.
public interface Subscription { void request(long n); void cancel(); }A Subscription has several important responsibilities:
-
Requesting Data: The
Subscriberuses theSubscriptionto request a certain number of data items from the Publisher. This is done through therequest(long n)method provided by the Subscription. The Publisher then sends the requested number of items to the Subscriber. -
Cancelling Subscription: The
Subscribercan use theSubscriptionto cancel (cancel()) its subscription to the Publisher at any time. This is important for managing resources and ensuring that the Publisher stops emitting data if the Subscriber is no longer interested. -
Backpressure: The
Subscriptionallows theSubscriberto implement backpressure, which is a mechanism that allows the Subscriber to control the rate at which it receives data from the Publisher. If the Subscriber becomes overwhelmed by data, it can use backpressure to signal the Publisher to slow down or stop emitting data temporarily.
-
-
Processor
Combines the roles of both publisher and subscriber. Processors transform, filter, or otherwise process items as they flow through the stream.
import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; public interface Processor<T, R> extends Subscriber<T>, Publisher<R> { }
Reactive Streams Workflow
The Reactive Streams workflow outlines how data flows and is processed through the different components of the reactive stream processing model, as defined by the Reactive Streams Specification. This workflow ensures that asynchronous data processing is efficient, non-blocking, and well-controlled, particularly in scenarios where data producers and consumers operate at different speeds.
High-level description of the Reactive Streams workflow:
-
Publisher:
- A data source, known as the Publisher, emits data items (events) asynchronously.
- It implements the
Publisherinterface and provides thesubscribe()method to establish a connection with aSubscriber. - The Publisher waits for a Subscriber to request data before emitting items.
- The Publisher pushes data to the Subscriber in response to requests.
- It implements the
- A data source, known as the Publisher, emits data items (events) asynchronously.
-
Subscriber:
- A data consumer, known as the Subscriber, receives and processes data items asynchronously.
- It implements the
Subscriberinterface and provides methods likeonSubscribe(),onNext(),onError(), andonComplete(). - When a Subscriber subscribes to a Publisher, it receives a Subscription object through the
onSubscribe()method. - The Subscriber requests data items from the Publisher by calling
request(n)on the Subscription. - Upon receiving data items via the
onNext()method, the Subscriber processes the items.
-
Subscription:
- A Subscription represents the connection between a Publisher and a Subscriber.
- It implements the
Subscriptioninterface and provides methods likerequest(n)andcancel(). - The Subscriber uses the Subscription to request a specific number (n) of data items from the Publisher.
- The Subscription allows the Subscriber to control the flow of data by requesting items and canceling the subscription when done.
-
Backpressure Handling:
- Backpressure is a mechanism that prevents a fast Publisher from overwhelming a slow Subscriber.
- The Subscriber signals its demand for items by calling
request(n)on the Subscription. - The Publisher should emit data items at a pace that matches the Subscriber’s requested demand.
- The Publisher should buffer or otherwise handle excess items if the Subscriber can’t keep up with the rate of emission.
-
Completion and Error Handling:
- When the Publisher has no more data to emit, it signals completion to the Subscriber by calling
onComplete()on the Subscriber. - If an error occurs during processing, the Publisher signals the error to the Subscriber by calling
onError(Throwable)on the Subscriber. - Upon receiving an error or completion signal, the Subscriber stops requesting items and performs any necessary cleanup.
- When the Publisher has no more data to emit, it signals completion to the Subscriber by calling
-
Processor (Optional):
- A Processor is an optional component that combines the roles of both Publisher and Subscriber.
- It implements the
Processorinterface and allows data transformation, filtering, and processing. - Processors can modify or transform data items as they flow through the stream, before delivering them to Subscribers.

Operators and Transformations
Operators and Transformations are used to modify, filter, combine, or otherwise transform the data as it flows through the stream. Let’s define these terms:
Operator
-
Operators are used to modify or manipulate the data emitted by a publisher (source) before it reaches a subscriber (consumer). They can perform operations like filtering, mapping, merging, and more.
-
Operators are typically chained together to create a pipeline of data transformations.
Transformation
A transformation is a specific type of operator that takes an input stream and produces an output stream where each element has been transformed in some way.
Common Operators and Transformations
-
map: Transforms each element emitted by the source stream using a provided function. For example, you can transform a stream of integers to their squares using the map operator.
-
filter: Filters the elements emitted by the source stream based on a provided predicate. Only elements that satisfy the predicate are allowed to pass through.
-
flatMap: Applies a function to each element emitted by the source stream, resulting in multiple output elements for each input element. The output elements are then merged into a single output stream.
-
merge: Combines multiple streams into a single output stream, interleaving the elements as they arrive from different sources.
-
concat: Concatenates multiple streams in a sequential manner, ensuring that the elements from the first stream are emitted before the elements from the second stream, and so on.
-
reduce: Aggregates the elements emitted by the source stream using an accumulator function, producing a single output element.
These are just a few examples, and there are many more operators and transformations available in Reactive Streams libraries like Reactor or RxJava.
JDK9 java.util.concurrent.Flow
The interfaces available in JDK >= 9 java.util.concurrent.Flow, are 1:1 semantically equivalent to their respective Reactive Streams counterparts.
This means that there will be a migratory period, while libraries move to adopt the new types in the JDK
Ref.
- https://www.youtube.com/watch?app=desktop&v=WcUlm4Yu56A&ab_channel=JavaTechie
- http://reactive-streams.org
- https://www.youtube.com/watch?v=AoJVZ2sdqSc&ab_channel=Engineerhoon
Get Started | Paradigms | Reactive Programming | Java | Java9