Java9 Part 4-Reactive Stream API Reactive Programming

file

I plan to write a series of articles about Java 9 in the next period of time. Although Java 9 is not a core Java version like Java 8 or Java 11, there are still many features worth paying attention to. Looking forward to your attention, I will write a series of articles about Java 9, about ten articles.

Java 9's Reactive Streams is an implementation of asynchronous streaming programming. It is based on an asynchronous publish and subscribe model and has the characteristics of non-blocking "back pressure" data processing.

Non-blocking Back Pressure: It is a mechanism that allows subscribers in the publish-and-subscribe model to avoid receiving large amounts of data (beyond its processing capacity), and subscribers can asynchronously notify the publisher to reduce or increase data production and release s speed. It is the core feature of responsive programming to achieve effects!

一、Java9 Reactive Stream API

Java 9 provides a set of interfaces for defining reactive stream programming. All these interfaces are defined in the java.util.concurrent.Flowclass as static internal interfaces .

file

The following are some important roles and concepts in Java reactive programming, first understand briefly

  • Publishers are producers of potentially unlimited number of ordered data elements. It publishes a certain number of data elements to current subscribers according to the received demand (subscription).
  • The subscriber (Subscriber) subscribes and receives data elements from the publisher. After establishing a subscription relationship with the publisher, the publisher sends a subscription token (subscription) to the subscriber, and the subscriber can request the publisher to publish the number of data elements according to their processing capabilities.
  • The subscription token (subscription) represents the subscription relationship established between the subscriber and the publisher. When the subscription relationship is established, the publisher passes it to the subscriber. The subscriber uses the subscription token to interact with the publisher, such as requesting the number of data elements or canceling the subscription.

Two, the four major interfaces of Java reactive programming

2.1. Subscriber Interface (Subscriber Subscription Interface)

public static interface Subscriber<T> {
    public void onSubscribe(Subscription subscription);
    public void onNext(T item);
    public void onError(Throwable throwable);
    public void onComplete();
}
  • onSubscribe: After the publisher accepts the subscriber's subscription action, it is called before publishing any subscription message. The newly created Subscriptionsubscription token object is passed to the subscriber through this method.
  • onNext: The processing function of the next data item to be processed
  • onError: called when the publisher or subscription encounters an unrecoverable error
  • onComplete: Called when no subscriber calls (including the onNext() method) occur.

2.2. Subscription Interface (Subscription Token Interface)

The subscription token object is passed through the Subscriber.onSubscribe()method

public static interface Subscription {
    public void request(long n);
    public void cancel();
}
  • request(long n)It is the key method behind the concept of non-blocking back pressure. Subscribers use it to request more than n consumption items. In this way, the subscriber controls how much data it can currently receive.
  • cancel()Subscribers take the initiative to cancel their subscriptions, and will not receive any data messages after cancellation.

2.3. Publisher Interface (Publisher Interface)

@FunctionalInterface
public static interface Publisher<T> {
    public void subscribe(Subscriber<? super T> subscriber);
}

Call this method to establish the message subscription relationship between the subscriber Subscriber and the publisher Publisher.

2.4. Processor Interface (Processor Interface)

The processor can act as a subscriber and a publisher at the same time, and play a role in transforming the elements in the publisher-subscriber pipeline. It is used to receive and convert data elements of type T into data elements of type R and publish them.

public static interface Processor<T,R> extends Subscriber<T>, Publisher<R> {
}

2. Actual case

Now we are going to implement the four interfaces above to complete reactive programming

  • Subscription Interface subscription token interface usually does not require our own programming to implement, we only need to know the meaning of the request() method and the cancle() method.
  • Publisher Interface publisher interface, Java 9 has provided us with the implementation of SubmissionPublisher by default. In addition to the methods that implement the Publisher interface, this implementation class provides a method called submit()to complete the sending of message data.
  • Subscriber Interface Subscriber interface, usually we need to implement it ourselves. Because after the data subscription is received, different businesses have different processing logic.
  • Processor is actually a collection of Publisher Interface and Subscriber Interface. Data type conversion and data processing are required to implement this interface.

The following example implements the data message subscription processing of the type string

Implement Subscriber Interface

import java.util.concurrent.Flow;

public class MySubscriber implements Flow.Subscriber<String> {

  private Flow.Subscription subscription;  //订阅令牌

  @Override
  public void onSubscribe(Flow.Subscription subscription) {
      System.out.println("订阅关系建立onSubscribe: " + subscription);
      this.subscription = subscription;
      subscription.request(2);
  }

  @Override
  public void onNext(String item) {
      System.out.println("item: " + item);
      // 一个消息处理完成之后,可以继续调用subscription.request(n);向发布者要求数据发送
      //subscription.request(n);
  }

  @Override
  public void onError(Throwable throwable) {
      System.out.println("onError: " + throwable);
  }

  @Override
  public void onComplete() {
      System.out.println("onComplete");
  }
}

SubmissionPublisher message publisher

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Flow;
import java.util.concurrent.SubmissionPublisher;

public class SubmissionPublisherExample {
  public static void main(String[] args) throws InterruptedException {
      ExecutorService executor = Executors.newFixedThreadPool(1);
      SubmissionPublisher<String> sb = new SubmissionPublisher<>(executor, Flow.defaultBufferSize());
      sb.subscribe(new MySubscriber());   //建立订阅关系,可以有多个订阅者
      sb.submit("数据 1");  //发送消息1
      sb.submit("数据 2"); //发送消息2
      sb.submit("数据 3"); //发送消息3

      executor.shutdown();
  }
}

The console prints out the result

订阅关系建立
onSubscribe: java.util.concurrent.SubmissionPublisher$BufferedSubscription@27e81a39
item: 数据 1
item: 数据 2

Please note: Even if the publisher submits 3 pieces of data, MySubscriber only receives 2 pieces of data for processing. It is because we used it in the MySubscriber#onSubscribe()method subscription.request(2);. This is the responsive programming effect of "back pressure". As much data as I have the ability to process, I will notify the message publisher of how much data is given.

Welcome to follow my blog, there are many boutique collections

  • This article is reproduced indicate the source (en must not turn only the text): letters Gebo off .

If you think it is helpful to you, please like and share it for me! Your support is my inexhaustible creative motivation! . In addition, the author has output the following high-quality content recently, and I look forward to your attention.

Guess you like

Origin blog.csdn.net/hanxiaotongtong/article/details/109128389