Java的反应式流是一种新的编程模型,它在异步和事件驱动的环境下工作。反应式流的目的是为了解决传统的单线程或者多线程编程模型在高并发和大流量情况下的性能瓶颈。

反应式流的核心是Observable和Observer,Observable表示一个数据流,而Observer则表示这个数据流的消费者。Observable在数据流上产生事件,而Observer则对这些事件进行响应。反应式流的数据流是一种推式的流,Observable发布事件时不需要等待Observer接收,Observable会把事件推送给Observer,而不是Observer去轮询Observable。

Java的反应式流通常基于Reactor或RxJava等库,这些库提供了丰富的函数式编程API和运算符,可以非常方便地处理异步事件。这些库都提供了类似于Observable和Observer的抽象概念,可以用来描述和处理异步数据流。同时还提供了常用的运算符,包括map、filter、reduce等,这些运算符可以方便地对数据流进行变换和过滤。

反应式流还有一个重要的概念是背压(backpressure),它是指在高并发和大流量情况下,消费者无法处理生产者产生的数据流,导致数据积压的情况。为了解决这个问题,反应式流引入了背压机制,生产者会在发送数据前先询问消费者的处理能力,如果消费者没有处理能力,生产者会等待一段时间或者缓存数据,等待消费者处理完数据后再继续发送。

反应式流已经被广泛应用于大规模的互联网应用中,包括机器学习、数据分析、网络爬虫等领域。它的优点在于处理高并发和大流量的数据流时,能够更加高效地利用系统资源,提高系统的性能和可扩展性。

总之,反应式流是Java编程中的一个重要概念,它可以帮助我们更好地处理异步和事件驱动的数据流,提高系统的性能和可扩展性。

不涉及任何库,就单纯用java的反应式流,完成发布订阅者模式:

package com.example.jdk9.react;

import java.util.concurrent.Flow.*;

public class PublisherSubscriberDemo {
public static void main(String[] args) {
SimplePublisher<String> publisher = new SimplePublisher<>();
SimpleSubscriber<String> subscriber1 = new SimpleSubscriber<>();
SimpleSubscriber<String> subscriber2 = new SimpleSubscriber<>();
publisher.subscribe(subscriber1);
publisher.subscribe(subscriber2);
publisher.submit("hello");
publisher.submit("world");
publisher.close();
}
} class SimplePublisher<T> implements Publisher<T> {
private Subscription subscription; @Override
public void subscribe(Subscriber<? super T> subscriber) {
subscriber.onSubscribe(new Subscription() { @Override
public void request(long n) { } @Override
public void cancel() { // nothing to do
}
}); this.subscription = new Subscription() {
private boolean cancelled = false; @Override
public void request(long n) {
// nothing to do
} @Override
public void cancel() {
this.cancelled = true;
} public boolean isCancelled() {
return this.cancelled;
}
}; subscriber.onSubscribe(this.subscription);
} public void submit(T item) {
subscriptionLimitedQueue.offer(item);
subscription.request(1);
} public void close() {
while (!subscriptionLimitedQueue.isEmpty()) {
subscriptionLimitedQueue.poll();
}
subscription.cancel();
} private SubscriptionLimitedQueue<T> subscriptionLimitedQueue = new SubscriptionLimitedQueue<>(2); static class SubscriptionLimitedQueue<T> {
private final int limit;
private int size = 0;
private Node<T> head;
private Node<T> tail; public SubscriptionLimitedQueue(int limit) {
this.limit = limit;
} private static class Node<T> {
final T item;
Node<T> next; Node(T item, Node<T> next) {
this.item = item;
this.next = next;
}
} public void offer(T item) {
Node<T> node = new Node<>(item, null);
if (head == null) {
head = node;
tail = head;
} else {
tail.next = node;
tail = tail.next;
}
size++;
if (size > limit) {
Node<T> newHead = head.next;
head.next = null;
head = newHead;
size--;
}
} public boolean isEmpty() {
return size == 0;
} public T poll() {
if (isEmpty()) {
return null;
}
T item = head.item;
Node<T> newHead = head.next;
head.next = null;
head = newHead;
size--;
return item;
}
}
} class SimpleSubscriber<T> implements Subscriber<T> {
private Subscription subscription; @Override
public void onSubscribe(Subscription subscription) {
this.subscription = subscription;
System.out.println("订阅成功");
subscription.request(1);
} @Override
public void onNext(T item) {
System.out.println("Received item: " + item);
subscription.request(1);
} @Override
public void onError(Throwable throwable) {
throwable.printStackTrace();
} @Override
public void onComplete() {
System.out.println("Done");
}
}

这段代码演示了使用Flow API来发布和订阅消息的过程,它包含以下类和接口:

  1. Publisher<T>:发布者接口,表示能够发布指定类型的消息给订阅者。
  2. Subscriber<T>:订阅者接口,表示能够接收指定类型的消息。
  3. Subscription:订阅接口,表示订阅关系,能够请求一定数量的消息和取消订阅。
  4. SubmissionPublisher<T>:继承自Publisher<T>接口,实现了异步发布消息的能力。
  5. Flow API:一组用于处理数据流和异步操作的接口和类。

具体解释:

  1. SimplePublisher类是一个实现了Publisher接口的简单发布者类,它能够发布指定类型的消息给订阅者。它内部维护了一个SubscriptionLimitedQueue类的对象,用于限制消息队列的长度。
  2. SubscriptionLimitedQueue类是一个维护队列长度的类,用于实现限制消息队列长度的功能。
  3. SimpleSubscriber类是一个实现了Subscriber接口的简单订阅者类,它能够接收指定类型的消息,并将其输出到控制台中。
  4. main方法创建了一个SimplePublisher类的实例和一个SimpleSubscriber类的实例,然后将它们关联起来,最后向SimplePublisher类的实例中发布了两个消息,随后关闭了发布者。

运行结果:

例子:

第一步,引入依赖:

<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.5.11</version>
</dependency>

第二步,编写代码:

package com.example.jdk9.react;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; public class ReactiveStreamExample {
public static void main(String[] args) {
Flux<Integer> stream = Flux.range(1, 10); stream
.map(i -> i * 2)
.filter(i -> i % 3 == 0)
.flatMap(i -> Mono.just(i).zipWith(Mono.just(i * 3)))
.subscribe(System.out::println);
}
}

上面的代码首先创建了一个从1到10的数字列表,然后通过map操作符将每个元素乘以2,再使用filter操作符过滤掉不能被3整除的元素。接下来,使用flatMap操作符来创建一个新的流,该流将原始元素和该元素乘以3的结果合并在一起。最后,使用subscribe方法来订阅这个流并打印出每个元素的值。

这个例子展示了Reactor库中的一些常见操作符,包括mapfilterflatMap。通过这些操作符的链式调用,我们可以轻松地对数据流进行复杂的操作。在实际的应用中,我们可以根据具体的需求选择不同的操作符来实现所需的数据处理逻辑。

使用Reactor 库实现发布订阅者模式:

package com.example.jdk9.react;

import reactor.core.publisher.Flux;

public class PublisherSubscriberExample {
public static void main(String[] args) {
// 创建发布者
Flux<Integer> publisher = Flux.just(1, 2, 3, 4, 5); // 订阅者1:打印每个元素
publisher.subscribe(System.out::println); // 订阅者2:计算元素的总和并打印
publisher.reduce(0, Integer::sum)
.subscribe(total -> System.out.println("Sum = " + total));
}
}

java的反应式流的更多相关文章

  1. Reactive(2) 响应式流与制奶厂业务

    目录 再谈响应式 为什么Web后端开发的,对 Reactive 没有感觉 Java 9 支持的 Reactive Stream 范例 小结 扩展阅读 再谈响应式 在前一篇文章从Reactive编程到& ...

  2. JVM上的响应式流 — Reactor简介

    强烈建议先阅读下JVM平台上的响应式流(Reactive Streams)规范,如果没读过的话. 官方文档:https://projectreactor.io/. 响应式编程 作为响应式编程方向上的第 ...

  3. JVM平台上的响应式流(Reactive Streams)规范

    // Reactive Streams // 响应式流是一个倡议,用来为具有非阻塞后压的异步流处理提供一个标准.大家努力的目标集中在运行时环境(JVM和JavaScript)和网络协议上. 注:响应式 ...

  4. Java中的IO流(六)

    上一篇<Java中的IO流(五)>把流中的打印流PrintStream,PrintWriter,序列流SequenceInputStream以及结合之前所记录的知识点完成了文件的切割与文件 ...

  5. Java中的IO流(二)

    上一篇<Java中的IO流(一)>把学习IO流的字符流作了一下记录,本篇把字节流记录一下. 一,Java中的字节流 Java中的字节流的操作方式与字符流的操作方式大致相同,连方法名都是类似 ...

  6. Java中I/O流之轮换流

    Java 中的轮换流: 非常有用,可以把一个字节流转换成字符流. inputStreamReader, outputStreamReader Demo_1: import java.io.*; cla ...

  7. java基础之IO流(二)之字符流

    java基础之IO流(二)之字符流 字符流,顾名思义,它是以字符为数据处理单元的流对象,那么字符流和字节流之间的关系又是如何呢? 字符流可以理解为是字节流+字符编码集额一种封装与抽象,专门设计用来读写 ...

  8. Java 8创建Stream流的5种方法

    不知不觉间,Java已经发展到13了,来不及感慨时间过得真的太快了,来不及学习日新月异的技术更新,目前大多数公司还是使用的JDK8版本,一方面是版本的稳定,另一方面是熟悉,所以很多公司都觉得不升级也挺 ...

  9. Java reactor响应式编程

    转载自:https://www.cnblogs.com/lixinjie/p/a-reactive-streams-on-jvm-is-reactor.html 响应式编程 作为响应式编程方向上的第一 ...

  10. java中的Stream流

    java中的Stream流 说到Stream便容易想到I/O Stream,而实际上,谁规定"流"就一定是"IO流"呢?在Java 8中,得益于Lambda所带 ...

随机推荐

  1. Postgresql 批量插入命令COPY使用

    在很多场景下,我们经常会遇到将某个Excel或Csv文件中的数据,插入到Postgresql.对于这个需求,我们常规的处理办法就是将文件中的数据,按照文件表头名称转换成集合对象然后插入到数据库,当然这 ...

  2. 如何通过拼多多订单API接口获取订单详情

    要获取拼多多订单详情,可以使用以下接口: 1. API名称:pdd.order.detail.get 接口说明:此接口用于查询某个订单的详情信息. API文档地址:前往注册 调用该接口需要提供以下参数 ...

  3. Htttpclien循环自动生成图片,同时发送参数和文件,模拟http的post请求

    package org.jeecg.modules.bussiness.PostTests; import com.sun.tools.internal.xjc.reader.xmlschema.bi ...

  4. KRPANO开发拍摄拼图视频常用软件分享

    KRPano开发拍摄拼图视频常用软件分享,包含了KRPano开发,拼图,视频等软件. 包括如下软件: 全景照片拼接,全景照片查看,全景视频拼接,全景视频查看,全景视频插件,全景漫游制作,KRPano资 ...

  5. 解决Promise的多并发问题

    提起控制并发,大家应该不陌生,我们可以先来看看多并发,再去聊聊为什么要去控制它 多并发一般是指多个异步操作同时进行,而运行的环境中资源是有限的,短时间内过多的并发,会对所运行的环境造成很大的压力,比如 ...

  6. oracle监听配置与防火墙问题

    在建好pdb容器后,需配置网络,才能从客户端连接服务器端 1.首先查看pdb容器的服务名 lsnrctl status ... Service "19cdb" has 1 inst ...

  7. Django-rest-framework框架——请求与响应、视图组件

    目录 一 请求与响应 1.1 Request 1.1.1.1 常用属性 1).data 2).query_params 1.2 Response 1.1.2.1 构造方式 1.1.2.2 常用属性 1 ...

  8. 11. 用Rust手把手编写一个wmproxy(代理,内网穿透等), 实现健康检查

    11. 用Rust手把手编写一个wmproxy(代理,内网穿透等), 实现健康检查 项目 ++wmproxy++ gite: https://gitee.com/tickbh/wmproxy gith ...

  9. 【高手训练】【RMQ】奶牛排队

    第一题由于过水,就没写awa 大概就是这样了.题意就是求一个最长的区间使得区间的左边是它的最小值,区间右边是他的最大值第一个想法肯定是暴力枚举啦awa但是这个是O(n^3)的,绝对的不可过awa 思考 ...

  10. [NOI2014] 字符串(题解)

    字符串(题解) 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学向游客要吃的,园长决定开设算法班,让动物们学 ...