是否有一种惯用的方法来处理副作用scala.concurrent.Future
,而在调用方中实际上并不需要其结果(即,计算调用方法的返回值既不需要成功也不必失败)?例如,
object XYZ {
def log(s: String): Future[Unit] = ???
}
仅调用XYZ.log("xyz")
而没有任何回调并继续执行真正重要的任务是否正确?这个孤儿的未来会不会被认为是代码的味道?在执行之前有机会对其进行垃圾回收吗?
答案 0 :(得分:2)
这个孤儿的未来不会被认为是代码气味吗?
不超过任何其他丢弃的非Unit
值。请注意,有些人do consider any discarded value to be a code smell,这就是-Ywarn-value-discard
和NonUnitStatements
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)
通过从线程池中分离主要业务逻辑线程池(出于侧面考虑),我们最大程度地减少了通过资源匮乏等破坏主要业务逻辑的机会。