Future(blocking(blockingCall()))
和blocking(Future(blockingCall()))
有什么区别?这两个都在scala.concurrent._
中定义
我看过at the scala docs和其他一些stack overflow answers,但不清楚它们之间有什么区别。
最佳答案
blocking
暗示其包含阻止代码的ExecutionContext
,因此它可以生成新线程以防止死锁。假定ExecutionContext
可以做到这一点,但并非全部做到了。
让我们一一看一下。
Future(blocking(blockingCall()))
这需要隐式的
ExecutionContext
来执行Future
。如果正在使用的ExecutionContext
是BlockContext
(就像scala.concurrent.ExecutionContext.Implicits.global
一样),则它可能能够在其线程池中生成一个新线程来处理阻塞调用(如果需要)。如果不是,则不会发生任何特殊情况。blocking(Future(blockingCall()))
这告诉我们
Future(blockingCall())
可能是一个阻塞调用,因此与上面相同。除了这里,Future.apply
是非阻塞的,因此有效地使用blocking
只会增加一点开销。我们从这里调用什么ExecutionContext
都没有关系,因为它始终没有被阻止。 但是,Future
中的阻塞调用将阻塞正在其上运行的ExecutionContext
中的线程,而没有暗示其阻塞的提示。因此,没有理由这样做。我已经在this answer中更深入地解释了
blocking
。REPL示例:
import java.util.concurrent.Executors
import scala.concurrent._
val ec = scala.concurrent.ExecutionContext.Implicits.global
val executorService = Executors.newFixedThreadPool(4)
val ec2 = ExecutionContext.fromExecutorService(executorService)
def blockingCall(i: Int): Unit = { Thread.sleep(1000); println("blocking call.. " + i) }
// Spawns enough new threads in `ec` to handle the 100 blocking calls
(0 to 100) foreach { i => Future(blocking(blockingCall(i)))(ec) }
// Does not spawn new threads, and `ec2` reaches thread starvation
// execution will be staggered as threads are freed
(0 to 100) foreach { i => Future(blocking(blockingCall(i)))(ec2) }
// `blocking` does nothing because the `Future` is executed in a different context,
// and `ec2` reaches thread starvation
(0 to 100) foreach { i => blocking(Future(blockingCall(i))(ec2)) }
// `blocking` still does nothing, but `ec` does not know to spawn new threads (even though it could)
// so we reach thread starvation again
(0 to 100) foreach { i => blocking(Future(blockingCall(i))(ec)) }
关于scala - Scala中的阻塞关键字,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31030119/