Java CompletableFuture 流式编程最佳实践?

nthin0

  • 虽然在很多地方看到有人说 java8 里的 CompletableFuture 是个残品,忍不住还是想在项目中用用,然后就碰到几个很蛋疼的问题

重试

  • 在 CompletableFuture 里调 rest 接口,发现没有自带的重试机制,比如根据响应码重试,根据 exception 类型重试,根据特定的响应内容重试。。。
  • 解决:引入第三方框架Failsafe,目前跟 CompletableFuture 搭配使用感觉还不错,需要的功能都有了

任务顺序

  • 有时候想在一个任务处阻塞住,等其他任务完成;有时候需要多个任务并发完成。目前没办法在一条流式语句中完成所有任务,需要拆成多个 CompletableFuture,再进行组合
    • “一条流式任务”指类似这种
    CompletableFuture.supplyAsync(...)
    	.thenCompose(...)
      .thenApply(...)
      .thenRun(...)
      .thenxxx(...)
      .whenComplete((v, ex) -> ...);
    
  • 用.thenCompose(v -> CompletableFuture.supplyAsync(() -> doWork(v), executor))时任务会停下等 doWork 完成,用.thenRun(() -> doWork2())的时候不会。。。
    • 这个地方应该是我理解还不够,没有理清楚 thenCompose 、thenCombine 、thenAccept 、thenRun 、thenApply 中哪些是能够“阻塞”的,哪些是不能的

一条流式语句中目前没解决的问题

whenComplete

  • 在一条流式语句中完成所有任务就不用写多个 whenComplete,把所有任务中出现的异常都能放到一个 whenComplete 统一处理。

需要多个参数参与任务流转的问题

String doWork1(){}

Integer doWork2(String work1Result){}

String finalWork(String work1Result, Integer work2Result){}

CompletableFuture.supplyAsync(doWork1)
  	.thenCompose(doWork2)
    .thenRun(someWork) //someWork 中并不需要 work1 和 work2 的结果
    .thenCompose(finalWork)
  • 但是为了能够将 work1 和 work2 的结果传递到 finalWork,就必须要在 someWork 中强行加上入参,再原样放到返回中

  • 解决:所有方法一律入参 tuple,返回 tuple,方法中只取需要的值,其他值放在 tuple 中往后流转。但是方法显得不够模块,很冗余,而且对后面维护代码的人很不友好

    • vavr框架中的 tuple2 tuple3...(通过 map1 、update1 )或者 either 还是比较好用的,弥补了一部分原生 java 的缺陷
  • 感觉最近对函数式编程、函子这些比较入迷,有大佬能推荐一下 java8 中使用 CompletableFuture 的正确姿势吗,或者关于函数式编程比较好的教程

yamasa:1.想学 FP,java 是很不适合的语言。要真正理解思想应该考虑学下 Lisp 的一些方言。反正国内这环境你也指望不了这些语言吃饭,就当是修炼内功了。
2.实在要在 java 里面搞,上 reactor 啊,比 cf 那一套残次品真的完成度高太多了,只要业务是真的 async 的,可以做到一把梭哈完。

Java 初级后端岗位竞争太激烈了吧

joyhub2140:小公司,9 月初开放一个 java 后端,6k 其,学历放松到大专,年限放宽到应届。到目前为止,11 天的时间,500 个人过来撩,大专和本科比例大概 9 比 1,还能见到几个 211 本科的。太恐怖了。drydiy:因为相比其他行业,互联网行业平均薪资算不错了,再加上各种培训班的鼓吹,造成这种现象很正常。 TypeError:Java…

Java 怎么实现条件编译?

enenaaa:java 基础为零。维护的代码里,有个类引用到了 sun.awt.X11 。但是又想能跨平台编译,起码在 windows 和 linux 都能用。怎么屏蔽平台差异呢? 难道只能运行时加载类库么。czzt1:不需要处理的吧,直接可以跨平台的 wanglulei:jvm 了解一下,java 如何实现跨平台? wysnylc:去了解下 JVM 跨平…

Java:正则表达式模式匹配器是否有大小限制? - java

我的模式类似于OR:“word1 | word2 | word3”我大约有800个字。可能有问题吗? 参考方案 您仅受记忆和理智的限制。 :)

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

在Zip文件中以编程方式创建链接-Java - java

我正在使用ZipOutputStream创建一个zip文件。也将有一个清单文件(一个csv文件),该文件具有指向Zip文件中条目的链接。如何以编程方式为zip条目创建链接? 参考方案 如果在编写它们时跟踪所有条目,则应该能够添加另一个包含“链接”的条目(但是csv如何链接到文件?请指定要实现的目标)。如果打算在Windows下使用该文件,则可以以编程方式创建…