斯卡拉的孤儿期货

时间:2019-12-06 13:08:15

标签: scala asynchronous future

是否有一种惯用的方法来处理副作用scala.concurrent.Future,而在调用方中实际上并不需要其结果(即,计算调用方法的返回值既不需要成功也不必失败)?例如,

object XYZ {
  def log(s: String): Future[Unit] = ???
}

仅调用XYZ.log("xyz")而没有任何回调并继续执行真正重要的任务是否正确?这个孤儿的未来会不会被认为是代码的味道?在执行之前有机会对其进行垃圾回收吗?

2 个答案:

答案 0 :(得分:2)

  

这个孤儿的未来不会被认为是代码气味吗?

不超过任何其他丢弃的非Unit值。请注意,有些人do consider any discarded value to be a code smell,这就是-Ywarn-value-discardNonUnitStatements wart存在的原因。

  

在执行之前是否有机会对其进行垃圾回收?

Future对象本身可能已被垃圾回收,但是它将向线程池提交一个不会提交的任务(因为该线程池包含对该任务的引用)。

之类的情况除外
def log(s: String): Future[Unit] = Future.just(())

当然。

答案 1 :(得分:1)

当我们拥有这样的Future时,它们不是主要业务逻辑的一部分,而是出于副作用而执行的,即代表诸如日志记录之类的单独问题,然后考虑在单独的专用执行上下文中运行它们。例如,使用

创建一个单独的池
val numOfThreads = 2
val threadPoolForSeparateConcerns = Executors.newFixedThreadPool(numOfThreads, (r: Runnable) => new Thread(r, s"thread-pool-for-separate-concerns-thread-${Random.nextInt(numOfThreads)}"))
val separateConcernsEc = ExecutionContext.fromExecutor(threadPoolForSeparateConcerns)

,然后在运行单独的关注点时确保将其传递

object XYZ {
  def log(s: String, ec: ExecutionContext): Future[Unit] = ???
}

XYZ.log("Failed to calculate 42", separateConcernsEc)

通过从线程池中分离主要业务逻辑线程池(出于侧面考虑),我们最大程度地减少了通过资源匮乏等破坏主要业务逻辑的机会。