Reactive stream-responsive stream

Source: Internet
Author: User

First knowledge of reactive Stream

Reactive stream (response flow/reaction flow) is a set of standards introduced by JDK9 and is a set of data processing specifications based on the publish/subscribe pattern. The response stream began in 2013 as an initiative to provide an asynchronous stream processing standard for non-blocking back pressure. It is designed to solve the problem of handling element flow-how to pass an element stream from the publisher to the Subscriber without requiring the publisher to block, or if the Subscriber has unlimited buffers or drops. Rather, the reactive stream is designed to "find the smallest set of interfaces, methods, and protocols that describe the necessary operations and entities to achieve this goal: asynchronous flow of data with non-blocking back pressure".

The concept of Back pressure (reverse pressure) pressure is critical. First, the asynchronous consumer will subscribe to the producer to receive the message, and then when there is new information available, the consumer will be re-activated by the callback function provided by the previous subscription. If producers send more information than consumers can handle, consumers may be forced to keep up with the news, consuming more and more resources and burying the potential crash risk. To prevent this, a mechanism is needed to enable consumers to inform producers and to reduce the speed at which messages are generated. Producers can use a variety of strategies to achieve this requirement, which is called back pressure.

The responsive flow model is simple--the subscriber sends an asynchronous request to the publisher for multiple elements, and the publisher asynchronously sends multiple or fewer elements to the subscriber. A responsive flow dynamically switches between the pull model and the push model flow processing mechanism. When the subscriber is slow, it uses the pull model, which is used faster when subscribers use the push model.

Simply put, a subscriber can communicate with a publisher in a responsive stream, and if you use JMS you should know that subscribers can only passively receive message data from publishers. This is like a water pipe without a faucet, I can only passively receive water flowing through the pipe, can not be closed and can not be reduced. The response flow is equivalent to adding a faucet to the water pipe, which allows the consumer to control the increase, decrease and closure of the water flow.

Response Flow Model Diagram:

Publisher (publisher) is a potential producer of an infinite number of ordered elements. The publisher may have more than one pending request from the Subscriber.

    • Publishes (or sends) elements to the current subscriber according to the request received.

Subscribers (subscriber) subscribe to and receive elements from the publisher. Subscribers can request more elements.

    • The publisher sends the subscription token (Subscription) to the Subscriber.
    • With subscription tokens, Subscribers request multiple elements from the publisher.
    • When the element is ready, the publisher sends multiple or fewer elements to the subscriber.
Reactive Stream Main Interface

JDK9 uses Java.util.concurrent.Flow and Java.util.concurrent.SubmissionPublisher classes to implement a responsive flow. In JDK9 the main interface of the reactive stream is declared in the flow class, the flow class defines four nested static interfaces that are used to establish traffic-controlled components in which the publisher generates one or more data items for subscribers to use:

    • Publisher: Data item Publishers, producers
    • Subscriber: Data item subscribers, consumers
    • Subscription: The relationship between the Publisher and the Subscriber, subscribing to the token
    • Processor: Data Processor

The flow class structure is as follows:

PublisherIs the publisher who can emit the element, the Subscriber subscriber who receives the element and responds. When executing Publisher the method, the subscribe Publisher will callback the subscriber's method, onSubscribe in this method, usually the subscriber will use the incoming to the Subscription Publisher to request n data. The publisher then onNext sends a maximum of n data to the Subscriber by calling the Subscriber's method continuously. If the data is all out, it is called to inform the Subscriber that the onComplete stream has been sent out, and if an error occurs, the onError stream is also terminated by issuing the wrong data.

The Subscription equivalent is the connection Publisher and Subscriber the "bond". Because when a publisher invokes subscribe a method to register a subscriber, it passes through the object through the Subscriber's callback method onSubscribe Subscription , and the subscriber can then use the Subscription object's request method to "want" the data to the publisher. Back pressure mechanism is based on this to achieve.

Such as:

Processoris set Publisher and Subscriber in one, equivalent to a "middleman" between the publisher and the Subscriber, by Processor doing some intermediate operations:

/** * A component that acts as both a Subscriber and Publisher. * * @param <T> the subscribed item type * @param <R> the published item type */public static interface Processor<T,R> extends Subscriber<T>, Publisher<R> {}

Such as:

Reference:

78175962

Sample Response Flow Usage

1. The following code briefly demonstrates the basic use of submissionpublisher and this set of publish-subscribe frameworks:

Package Com.example.demo;import java.util.concurrent.flow;import java.util.concurrent.submissionpublisher;/** * @ Program:demo * @description: Flow Demo * @author: $ * @create: 2018-10-04 13:25 **/public class Flowdemo {public STA tic void Main (string[] args) throws Exception {//1. Define the publisher, the published data type is Integer//directly using the JDK's own submissionpublish        Er, which implements the Publisher interface submissionpublisher<integer> publiser = new submissionpublisher<> (); 2. Define Subscriber flow.subscriber<integer> subscriber = new flow.subscriber<> () {Private flow.subscript            Ion subscription;                @Override public void Onsubscribe (Flow.subscription Subscription) {//Save the subscription relationship, it needs to be used to respond to the publisher                This.subscription = subscription;            Request a data this.subscription.request (1); } @Override public void OnNext (Integer item) {//received to a data processing SYSTEM.OUT.PRINTLN ("Receive data:" + Item);                After processing call request one more data this.subscription.request (1);            Or you have reached the target, you can call Cancel to tell the publisher that no longer accepts the data//This.subscription.cancel ();                } @Override public void OnError (Throwable throwable) {//An exception occurred (for example, an exception was generated when processing data)                Throwable.printstacktrace ();            We can tell the publisher that the data is not accepted later this.subscription.cancel (); } @Override public void OnComplete () {///All data processing finished (publisher closed) System.out.            println ("Finished!");        }        }; 3.        Publisher and subscriber establish subscription relationship publiser.subscribe (subscriber); 4.            Production data, and publish//Here ignore data production process for (int i = 0; i < 3; i++) {System.out.println ("Generate Data:" + i);        Submit is a block method Publiser.submit (i); }//5. Close Publisher//formal environment should be put finally or use try-resouce to ensure close publiser.close ();       The main thread delay is stopped, otherwise the data will exit Thread.CurrentThread () without consumption. Join (1000);    Debug, the following line needs to have a breakpoint//or the main thread end can not debug System.out.println (); }}

The results of the operation are as follows:

As mentioned above, you can adjust the data output speed of the publisher, so how is this speed adjusted? The key is the Submit method, which is a blocking method. It is important to note that there is a data buffer in the Submissionpublisher that buffers the data generated by the publisher, and this buffer is implemented using an object array with a maximum buffer length of 256. We can make a breakpoint in the Onsubscribe method to see the buffer:

When the buffer data is full, the Submit method will enter the blocking state, the publisher data will be produced slowly, so as to adjust the publisher's data output speed.

2. The second example demonstrates the use of a combination of processor, with the following code:

Package Com.example.demo;import Java.util.concurrent.flow.processor;import Java.util.concurrent.Flow.Subscriber; Import Java.util.concurrent.flow.subscription;import java.util.concurrent.submissionpublisher;/** * Processor, Need to inherit Submissionpublisher and implement processor interface * * Input source data integer, filter out less than 0, and then convert to a string published */class Myprocessor extends Submissionpublisher<string> implements Processor<integer, string> {private Subscription Subscriptio    N  @Override public void Onsubscribe (Subscription Subscription) {//Saves the subscription relationship, which needs to be used to respond to the publisher this.subscription =        Subscription    Request a data this.subscription.request (1);         } @Override public void OnNext (Integer item) {//received to a data processing System.out.println ("Processor received data:" + Item);        Filter out less than 0, then publish if (item > 0) {this.submit ("converted data:" + Item);        }//After processing the call request one more data this.subscription.request (1); Or if the target is reached, cancel is called to tell the publisher to no longer accept the data/thIs.subscription.cancel (); } @Override public void OnError (Throwable throwable) {//An exception occurred (such as an exception when processing data) THROWABLE.PRINTSTACKTR        Ace ();    We can tell the publisher that the data is not accepted later this.subscription.cancel ();        } @Override public void OnComplete () {//All data processed (publisher closed) System.out.println ("Processor finished!");    Close publisher This.close (); }}/** * Flow demo * With process @author */public class FlowDemo2 {public static void main (string[] args) throws Exc eption {//1. To define the publisher, the published data type is Integer//directly using the JDK's own submissionpublisher Submissionpublisher<intege        r> publiser = new submissionpublisher<> (); 2.        Define the processor, filter the data, and convert to String type Myprocessor processor = new Myprocessor (); 3.        Publisher and processor establish a subscription relationship publiser.subscribe (processor); 4. Define end subscribers, consume String type data subscriber<string> subscriber = new subscriber<> () {Private SUBSCRI            Ption subscription; @Override public void Onsubscribe (Subscription Subscription) {//Save the subscription relationship, which needs to be used to respond to the publisher                This.subscription = subscription;            Request a data this.subscription.request (1); } @Override public void OnNext (String item) {//accepts a data to handle System.ou                T.PRINTLN ("Receive data:" + Item);                After processing call request one more data this.subscription.request (1);            Or has reached the target, call Cancel to tell the publisher no longer to accept the data//This.subscription.cancel ();                } @Override public void OnError (Throwable throwable) {//An exception occurred (for example, an exception was generated when processing data)                Throwable.printstacktrace ();            We can tell the publisher that the data is not accepted later this.subscription.cancel (); } @Override public void OnComplete () {///All data processing finished (publisher closed) System.out.            println ("Finished!");  }        };      5.        The processor and the end Subscriber establish a subscription relationship processor.subscribe (subscriber); 6.        Production data, and publish//Here ignore Data production process Publiser.submit (-111);        Publiser.submit (111); 7.        Close Publisher//formal environment should be put finally or use try-resouce to ensure close publiser.close ();    The main thread delay is stopped, otherwise the data does not consume to exit Thread.CurrentThread (). Join (1000); }}

The results of the operation are as follows:

Reactive stream-responsive stream

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.