V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nthin0
V2EX  ›  Java

Java CompletableFuture 流式编程最佳实践?

  •  
  •   nthin0 · 2020-09-22 11:04:24 +08:00 · 4299 次点击
    这是一个创建于 1557 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • 虽然在很多地方看到有人说 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 的正确姿势吗,或者关于函数式编程比较好的教程

    18 条回复    2020-12-24 16:06:34 +08:00
    yamasa
        1
    yamasa  
       2020-09-22 11:58:58 +08:00   ❤️ 1
    1.想学 FP,java 是很不适合的语言。要真正理解思想应该考虑学下 Lisp 的一些方言。反正国内这环境你也指望不了这些语言吃饭,就当是修炼内功了。
    2.实在要在 java 里面搞,上 reactor 啊,比 cf 那一套残次品真的完成度高太多了,只要业务是真的 async 的,可以做到一把梭哈完。
    hdfg159
        2
    hdfg159  
       2020-09-22 12:50:08 +08:00 via Android
    emmm,用 RxJava 去了
    zoharSoul
        3
    zoharSoul  
       2020-09-22 13:36:29 +08:00   ❤️ 1
    CompletableFuture 就是个残废.
    建议一步到位直接 rxjava 或者 kotlin 协程
    nthin0
        4
    nthin0  
    OP
       2020-09-22 13:43:12 +08:00 via iPhone
    @yamasa 感谢🙏,只是想提升下内功多接触一些函数式的思想,日常 crud 一把梭能用上的地方不多,准备去学习下 rxjava 了。
    nthin0
        5
    nthin0  
    OP
       2020-09-22 13:44:15 +08:00 via iPhone
    @zoharSoul 深有同感,现有的 cf 实现局限性太太太多了,准备看看 rxjava,多谢🙏
    Skhizein
        6
    Skhizein  
       2020-09-22 13:55:20 +08:00 via iPhone
    听上去好像存在银弹似的
    jelipo
        7
    jelipo  
       2020-09-22 13:58:23 +08:00 via Android
    写业务就算了,心智负担比较高,你能写出来同事也看不懂
    上 kotlin 协程
    wysnylc
        8
    wysnylc  
       2020-09-22 14:10:50 +08:00
    没有银弹
    rulework
        9
    rulework  
       2020-09-22 14:14:47 +08:00
    建议学下 scala
    AllanAG
        10
    AllanAG  
       2020-09-22 14:29:06 +08:00
    RxJava 在安卓上使用较多,后端的话的有 Spring 的 Reactor,网络相关的 reactor-netty
    ychost
        11
    ychost  
       2020-09-22 15:08:43 +08:00
    撸的最多的还是 Stream,RxJava 撸多了发现 Java 不适合
    rim99
        12
    rim99  
       2020-09-22 15:10:38 +08:00
    CompletableFuture/CompletableStage 感觉适合作为最终输出的类型使用,中间过程用 RxJava 之类的 Reactive Stream 类库更合适
    qiyuey
        13
    qiyuey  
       2020-09-22 15:18:59 +08:00
    换 Kotlin 协程吧,这个写起来太麻烦了
    nthin0
        14
    nthin0  
    OP
       2020-09-22 15:19:46 +08:00
    @jelipo 考虑其他同事的学习成本,公司项目上 kotlin 可能性不大,只能先熟悉函数式编程练一下内功
    nthin0
        15
    nthin0  
    OP
       2020-09-22 15:20:07 +08:00
    @AllanAG 👌👌 多谢
    nthin0
        16
    nthin0  
    OP
       2020-09-22 15:23:14 +08:00
    @qiyuey 公司项目上 kotlin 可能性不大,准备拿个人项目练练手
    BBCCBB
        17
    BBCCBB  
       2020-12-24 16:06:18 +08:00
    最近我也在找 completablefuture 重试.. 发现 failsafe 这个库可以实现.不自带的确很难受.
    BBCCBB
        18
    BBCCBB  
       2020-12-24 16:06:34 +08:00
    楼主已经发现了哈哈
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2837 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 03:00 · PVG 11:00 · LAX 19:00 · JFK 22:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.