如何最好地实例化执行上下文?

How best to instantiate execution contexts?

我正在建立其他人的图书馆——即那些对内部不感兴趣的人——可以用来从我们的数据库中提取数据。在内部,出于性能目的,我希望并行执行几个 I/O 调用。这里的权衡是客户端(同样,可能不太关心整个线程的事情)需要提供适当的执行上下文。因此,我建议在辅助对象中使用有用的执行上下文:

object ThreadPoolHelper {
  val cachedThreadPoolContext: ExecutionContext =
    ExecutionContext.fromExecutor(Executors.newCachedThreadPool())
}

问题是(假设有一天我还提供其他选项,比如,一个固定的线程池供客户选择使用)我可以把这个(这些)作为一个 val 吗?或者我最好让它变得懒惰?还是 def?

不管怎样,懒惰才是王道。

使它们成为 lazy val 将是一个很好的通用选择,因为每个都可以根据需要进行初始化(当它们被访问时)。然后,您永远不会初始化比需要更多的线程池。 scala.concurrent.ExecutionContext.Implicits.global 是一个 implicit lazy val.

从技术上讲,单例对象(如 ThreadPoolHelper)默认情况下是惰性的,因此在首次访问它们之前不会对其进行初始化。如果 object 中只有一个 ExecutionContext,val 就可以了。但是,在同一个对象中使用多个 ExecutionContext 作为 val 没有多大意义,因为访问一个会初始化它们——这将使用比需要更多的资源。

A def 没有意义,因为那样的话你会在每次调用时创建一个新的 ExecutionContext,并在完成后将其丢弃。这可能会导致很多不必要的开销,并且默认首先要有一个线程池。

有些 ExecutionContext 比您的稍微更自定义一些 object 是扩展 ExecutionContext 并实现自己的自定义行为的单例 object。这些也会很懒惰。