Java 多线程导致 Service 之间互相调用,有什么解耦或者优化办法吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
KamL
V2EX    Java

Java 多线程导致 Service 之间互相调用,有什么解耦或者优化办法吗?

  •  
  •   KamL 2023 年 3 月 24 日 2984 次点击
    这是一个创建于 1046 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前碰到一个需求,serviceA 向外发送数据,走完前调用 serviceB 开启一条支线程去重复持续获取操作结果,直到获取结果为止,然后更新 serviceA 的数据状态。 这样导致了 serviceA 调用 serviceB ,然后 serviceB 又要调用 serviceA ,造成了循环调用。 求问各位大佬有什么办法优化一下,另外有多线程和设计模式的书推荐一下嘛?谢!

    12 条回复    2023-03-25 08:21:19 +08:00
    xiaohundun
        1
    xiaohundun  
       2023 年 3 月 24 日
    这种为啥不用发布订阅或者基于事件的方式?
    shinyruo2020
        2
    shinyruo2020  
       2023 年 3 月 24 日
    这不就是回调吗,serviceA 传一个 Function 给 serviceB
    liudaolunhuibl
        3
    liudaolunhuibl  
       2023 年 3 月 24 日
    1 、你要解耦的话,就重新写一个 serviceC 来获取 A 的数据,serviceA 可以叫 producrService serviceC 就是 consumer Service ,A 负责发数据和写数据,C 负责读取查询,这样 A 发送完数据,调用 B ,B 调用 C 去查询数据,可以理解为读写分离
    2 、重复持续获取就是轮询吧 ,轮询不是非常的优雅,因为长时间的轮训会给 CPU 造成压力,最好是按照一楼说的基于事件驱动,也就是操作结果完成之后调用 B ,可以用 MQ 或者单节点就用谷歌的 eventBUs 或者 spring event
    3 、多线程和设计模式的书网上一搜一大把
    yazinnnn
        4
    yazinnnn  
       2023 年 3 月 24 日
    你用的啥客户端, 异步却不支持设置回调?

    client
    .send(xxx)
    .onSuccess(result-> handle(result))
    .onFailure(error->handle(error))

    这种形式的代码都不支持码?
    litchinn
        5
    litchinn  
       2023 年 3 月 24 日
    事件驱动
    serviceA 里发布事件,eventA.send()
    serviceB 作为一个 eventA 的监听器,执行完任务后再发送 eventB
    serviceA 里再包含一个 eventB 的监听器,监听到 B 事件后更新数据

    eventA 和 eventB 可以是同一个事件具有不同的状态,也可以是多个事件,看你的业务进行设计

    单体服务用多线程就可以了,分布式集群的话用 mq ,如 3 楼所说的方案
    KamL
        6
    KamL  
    OP
       2023 年 3 月 24 日
    @liudaolunhuibl
    @xiaohundun
    @litchinn
    非常感谢,大概找到方向了,我研究一下。

    @shinyruo2020 回调不太符合需求,但也感谢解答

    @yazinnnn 程序其实是操作工控设备,将参数 A 下发以后,等待执行完毕后获取结果。但是这个等待的时长不确定,而且这个结果只需要更新到数据库就行,除非程序遇到情况报错了,否则前端不太需要查看执行结果。
    nothingistru
        7
    nothingistrue  
       2023 年 3 月 24 日
    如果把 serviceA 、serviceB 看成两个独立的微服务,那么这就不是互相调用,是分布式事件流,虽然看起来比较乱,但是并没有耦合,因为每个 service 都是自成一体,仅通过接口跟外部沟通的。

    不过你这个还是有点耦合,需要稍微拆解一下。改成如下过程:
    -> A 在队列( A 让 B 处理)当中发送一条任务
    -> B 从队列收到任务后,执行,得出结果后,在另一个队列( B 返回结果给 A )上,发送处理结果
    -> A 从队列收到结果后,执行后续处理(更新数据状态、向外发送等)。

    注意一点:如果 A 之前还有调用者,那么 A 是无法向调用者返回最终执行结果的,因为 A 在第一个过程就必须终止同步处理,后面的全是异步的。
    zhuisui
        8
    zhuisui  
       2023 年 3 月 24 日
    解耦的关键是消除业务循环依赖关系,从来都不是程序的依赖关系。
    不管是程序内部的回调函数,还是程序外部的 rpc 或消息队列,或者是什么别的调用形式。
    A 委托 B 做一件事,那么 A 就要负责主动接受处理结果。
    几种调用方式上,提供回调明示了这个意图,其他异步方式较为隐晦。如果是 rpc ,应该 B 提供 rpc 给 A 进行委托处理和获取结果。如果是消息队列,应该由 B 声明两种工作的消息通道和内容。
    总结来说,就是 B 不知道 A 。
    winglight2016
        9
    winglight2016  
       2023 年 3 月 24 日
    工控设备居然用 java 操作?一般不是用串口线走 mobus 协议,只管轮询 /更新数据区这种方式吗?

    想模拟这种方式的话,用 redis 充当数据区就可以了
    Pony69
        10
    Pony69  
       2023 年 3 月 24 日
    mq 或者 redis 队列
    urnoob
        11
    urnoob  
       2023 年 3 月 24 日
    AB 是
    两个 jvm ,没问题啊(又不是不能用)
    两个类的 instance
    合二为一
    抽到 C
    学多线程,避免 hang 在那
    学多线程知识,避免 hang 在那里
    KamL
        12
    KamL  
    OP
       2023 年 3 月 25 日
    @winglight2016 这边大部分都是网口,西门子或是三菱的,直接通过 ip 地址读写数据块的信息。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4394 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 05:46 PVG 13:46 LAX 21:46 JFK 00:46
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86