scala中的理解半并行调用

Posted

技术标签:

【中文标题】scala中的理解半并行调用【英文标题】:For-comprehension semi-parallel calls in scala 【发布时间】:2021-08-16 14:36:01 【问题描述】:

我想在 seq 中对下一个调用进行第一次调用,然后使用 Scala 的期货进行下 10 个相互并行的调用。我不想对地图平面图或内部进行编程以进行理解,因为它们会增加不可读性。有没有可能理解的。

参考代码:

val fcaAndFplAccountDetails  = getFcaAndFplAccount(fplId)
def orgDetailsIO(orgId:Int)  = getOrgDetails(orgId)
def unbilledTxns(orgid: Int) = getUnbilledTxns(orgId)
for 
      accDetails   <- fcaAndFplAccountDetails
      orgDetails   <- orgDetailsIO(accDetails.orgId)
      unbilledTxns <- unbilledTxnsIO(accDetails.orgId)
      ... other calls that depend on org id
     yield  ... further computations 

fcaAndFplAccountDetails 之后的调用能否在理解中并行化?

【问题讨论】:

您的方法是返回 IO、Future 还是其他? 【参考方案1】:

必须有几十个选项,但一个是:

  val fcaAndFplAccountDetails : Future[Int] = ???
  def orgDetailsIO(orgId:Int)  : Future[_] = ???
  def unbilledTxns(orgid: Int) : Future[_] = ???
  for 
    accDetails   <- fcaAndFplAccountDetails
    (orgDetails, unbilledTxns)   <- Future.sequence(List(orgDetailsIO(accDetails), unbilledTxns(accDetails))).map(el => (el(0), el(1)))
 yield ()

你也可以使用Future.traverse

【讨论】:

值得一提的是,顾名思义,Future.sequence 不建议在并行中执行调用。 ***.com/questions/25056957/… @GaëlJ 实际上 future 在创建时仅在不同的线程中开始执行。所以Future.sequence 是并行的,因为里面的期货已经开始执行了。【参考方案2】:

对于应该并行执行的调用,可能会跟随一个使用等号定义值的生成器

for 
  accDetails    <- fcaAndFplAccountDetails
  orgDetailsF   = orgDetailsIO(accDetails.orgId)
  unbilledTxnsF = unbilledTxnsIO(accDetails.orgId)
  orgDetails    <- orgDetailsF
  unbilledTxns  <- unbilledTxnsF 
 yield  ... further computations 

或通过Applicative传达想法

import cats.implicits._

fcaAndFplAccountDetails.flatMap  accDetails =>
  (
    orgDetailsIO(accDetails.orgId),
    unbilledTxnsIO(accDetails.orgId)
  ).mapN((orgDetails, unbilledTxns) => 
    ... further computations  
  

【讨论】:

以上是关于scala中的理解半并行调用的主要内容,如果未能解决你的问题,请参考以下文章

使用Scala语言调用Flink框架进行WordCount词频统计测试不同Parallelism并行度对运算速度的影响

每天半小时掌握Scala(day 02)

Java基础中的一些概念理解

每天半小时掌握Scala(day 03)

以半并行方式运行多个任务

深入理解并发/并行,阻塞/非阻塞,同步/异步