带你读《2022技术人的百宝黑皮书》——如何避免写重复代码:善用抽象和组合(4)

简介: 带你读《2022技术人的百宝黑皮书》——如何避免写重复代码:善用抽象和组合(4)

带你读《2022技术人的百宝黑皮书》——如何避免写重复代码:善用抽象和组合(3)https://developer.aliyun.com/article/1339967?groupCode=taobaotech


实现 buffer

image.png

 

 

 

Source.fromJavaStream(() -> IntStream.rangeClosed(1, 10))
.statefulMap(
() -> new ArrayList<Integer>(3), (list, element) -> { list.add(element);
if (list.size() == 3) {
return Pair.create(new ArrayList<Integer>(3), Collections.unmodifiableList(list));
} else {
return Pair.create(list, Collections.<Integer>emptyList());
}
},
listOnComplete -> Optional.ofNullable(listOnComplete))
.filterNot(List::isEmpty)
.runForeach(System.out::println, system);
// prints List(1, 2, 3)
List(4, 5, 6)
List(7, 8, 9)
List(10)

 

更复杂的例子:处理资源

 

在前面看了如何实现 zipWithIndex 、bufferUntilChanged 之后,让我们进一步看看如何优雅和安全地处理资源。在任何的编程语言和框架中,资源的处理都是非常基础但是又很棘手的事项。在Java7 中首次引入了 try-with-re- sources 语法,对资源处理进行了一定程度的简化,而在反应式流中,我们又应该如何的操作呢?这里我们可以分为两种情况:

  1. 针对流中的每个元素都创建一个新的资源,使用这个资源,关闭这个资源。
  2. 针对整个流创建一个资源,并在处理流中的每个元素时使用这个资源,并在流的生命周期结束后,关闭这个资源。

 

因为资源通常开销较大且需要妥善管理,所以在开发过程中,我们更容易遇到的是 第2种情况,即资源的创建和销毁和流的生命周期进行了绑定。反应式流中的资源管理,还有更多的细节需要考虑:

 

 

 

  1. 资源的初始化和关闭需要支持并发安全;反应式流可以被多次物化,被多个下游订阅者订阅和处理,并且以任意的顺序进行取消订阅,需要在各种情况下(上游完成、下游取消、处理异常等)等情况下妥善的创建和销毁资源。
  2. 在流生命周期的各个阶段安全地创建和销毁资源;比如:即使在创建资源或者销毁资源的时触发了异常,也不会对同一个资源关闭多次。
  3. 支持异步从而提高资源使用的效率。
  4. 感知流的生命周期,支持在关闭资源时提供可选的值给到下游以标识流的结束,比如处理文件时,使用一个特殊的标识符标识文件的结尾。

 

综合上面的这些诉求,对应的代码就会变得很复杂,大家可以给自己一点时间思考一下:如果是自己独立实现类似的操作需要做出那些努力呢?而在现实的开发过程中,我们遇到的述求很多时候并非一起提出,而时随着迭代接踵而至,那么如果当初的代码编写的不是很易于扩展,拥有良好的测试,则可能按下葫芦浮起瓢。

 

比如在 reactor-core中就有如下的using 操作符:

  public static <T, D> Mono<T> using(
  Callable<? extends D> resourceSupplier,
  Function<? super D, ? extends Mono<? extends T>> sourceSupplier,
  Consumer<? super D> resourceCleanup) {...}

resourceSupplier 针对每个订阅者,创建一个资源sourceSupplier 结合创建的资源,产生对应的元素resourceCleanup 取消订阅或者流完成时,清理对应的资源

 

reactor-core 中,对应的底层实现为 MonoUsing360 行代码,而要实现我们想要的逻辑,我们还需要和另一个流进行合并,即这里的 using 类似于 unfoldResource 。那么有没有可能使用更加简单的方案来进行实现呢? 答案是肯定的,和前面的几个操作符一样,我们可以使用 statefulMap 来实现mapWithResource ,思维过程如下:

 

  1. using / mapWithResource 的生命周期管理 和 statefulMapcreateonComplete 方法对应,针对资源,onComplete 方法可以被命名为更加贴切的 release / close / cleanUp。
  2. 在流中使用的资源,我们可以认为是一个状态,只不过这个状态在流的整个生命周期中不再变化,一直是create 方法中返回的 Resource
  3. 在关闭资源时,我们可以通过返回一个 Optional> 来返回一个可选的值。
  4. 对并发资源的异步处理,则可以通过返回一个 CompletionStage> 而非 Out 来实现,在 using 方法中, 我们返回的是一个 Mono

 

 

 

经过上面的思维过程,我们不难得出这个流上的方法的声明可以为:

  public <R, In, Out> mapWithResource(
  Supplier<? extends R> create,
  BiFunction<? super R, ? super In, ? extends Out> function,
  Function<? super R, ? extends Optional<? extends Out> close) {...}

resourceSupplier 针对每个订阅者/每次物化,创建一个资源function 使用create 中创建的资源处理流中的每个元素

close 在流关闭的同时关闭资源,并再向下游提供一个可选的值

 

具体的的实现这里留空,感兴趣的小伙伴可以结合前面的例子进行实现。下面我们看一下如何使用这mapWi- thResource 方法,从而加深大家的理解。

 

带你读《2022技术人的百宝黑皮书》——如何避免写重复代码:善用抽象和组合(5)https://developer.aliyun.com/article/1339963?groupCode=taobaotech

相关文章
|
设计模式 Java
好好的“代码优化”是怎么一步步变成“过度设计”的(上)
好好的“代码优化”是怎么一步步变成“过度设计”的(上)
493 4
|
存储 设计模式 算法
DDD之于业务支撑的意义
DDD之于业务支撑的意义
346 0
|
存储 Kubernetes 监控
在K8S中,发布应用流程是什么?
在K8S中,发布应用流程是什么?
|
10月前
|
存储 前端开发 JavaScript
深入理解 ECMAScript 2024 新特性:Promise.withResolvers
ECMAScript 2024 引入了 `Promise.withResolvers`,简化了手动创建 `Promise` 时管理 `resolve` 和 `reject` 的复杂性。本文详细介绍其设计背景、使用方式,并通过多个实际案例展示其优势。该方法减少了代码冗余和潜在错误,使异步任务管理更加直观和简洁。未来,这一特性有望为前端开发带来更多灵活性和便利性。
233 37
|
数据安全/隐私保护 Python
解决CondaHTTPError:HTTP 000 CONNECTION FAILED for url<https://mirrors.tuna.tsinghua.edu.cn/anaconda***
今天做项目的时候,Python导入一个包一直有各类问题,而后最终锁定问题是CondaHTTPError:HTTP 000 CONNECTION FAILED for url<https://mirrors.tuna.tsinghua.edu.cn/anaconda*** 这就是清华的源出问题了,配置没配对。
解决CondaHTTPError:HTTP 000 CONNECTION FAILED for url<https://mirrors.tuna.tsinghua.edu.cn/anaconda***
|
前端开发 安全 关系型数据库
PHP在Web开发中的应用及其优势###
【10月更文挑战第16天】 — 本文探讨了PHP在现代Web开发中的广泛应用及其显著优势。通过分析PHP的核心特性,如灵活性、易用性和广泛的应用支持,阐述了为何PHP成为众多开发者和公司的首选技术。文章还介绍了PHP与其他编程语言的比较,并展望了其未来的发展趋势。 ###
214 2
|
机器学习/深度学习 运维 安全
容器化部署的运维之道
在当今快速发展的软件行业,容器技术已成为推动持续集成和持续交付的关键因素。本文深入探讨了容器化部署的优势、挑战以及最佳实践,旨在为运维人员提供一套全面的指导方案,帮助他们更好地利用容器技术优化部署流程,提升系统的稳定性与效率。
280 27
|
运维
【10月更文挑战赛】获奖名单出炉,快来看看谁是十月创作明星!
【10月更文挑战赛】获奖名单出炉,快来看看谁是十月创作明星!
354 9
|
12月前
|
存储 监控 数据可视化
双十一线上服务调用链路追踪SkyWalking实战分析
【11月更文挑战第27天】随着电商行业的飞速发展,双十一购物节已成为全球最大的购物狂欢节之一。在双十一期间,电商平台需要处理海量的用户请求和订单,这对系统的稳定性和性能提出了极高的要求。为了确保系统在高并发环境下的稳定运行,对线上服务的调用链路进行追踪和分析显得尤为重要。本文将通过实战案例,详细介绍如何在双十一期间使用SkyWalking对线上服务进行调用链路追踪,并结合Seata实现分布式事务管理,从而保障系统的稳定性和性能。
353 6