我总是选择第一个选项。但我以稍微不同的方式做到这一点。我不使用该功能。(实际上我还没有想过。相反,我正在为Future提供一个自定义执行上下文,用于包装同步阻塞调用。所以它基本上看起来像这样:blocking
val ecForBlockingMemcachedStuff = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(100)) // whatever number you think is appropriate
// i create a separate ec for each blocking client/resource/api i use
Future {
cache.get(key) //synchronous blocking call
}(ecForBlockingMemcachedStuff) // or mark the execution context implicit. I like to mention it explicitly.
因此,所有阻塞调用都将使用专用的执行上下文 (= Threadpool)。因此,它与负责非阻塞内容的主执行上下文分离。
Typesafe 提供的 Play/Akka 在线培训视频也解释了这种方法。第 4 课中有一个关于如何处理阻塞呼叫的视频。它由Nilanjan Raychaudhuri(希望我拼写正确)解释,他是Scala书籍的着名作者。
更新:我在推特上与Nilanjan进行了讨论。他解释了方法和习惯之间的区别是什么。该功能只是创建了一个特殊的.它为您需要多少线程的问题提供了一种朴素的方法。每次当池中的所有其他现有线程都处于繁忙状态时,它都会生成一个新线程。所以它实际上是一个不受控制的执行文本。它可能会创建大量线程并导致内存不足错误等问题。因此,具有自定义执行上下文的解决方案实际上更好,因为它使此问题变得明显。Nilanjan还补充说,如果此池的请求过载,您需要考虑断路。blocking
ExecutionContext
blocking
ExecutionContext
TLDR:是的,阻止呼叫很糟糕。使用自定义/专用的执行上下文来阻止调用。还要考虑断路。