在Scala中阻止关键字

Man*_*anu 11 io concurrency scala future

Future(blocking(blockingCall()))和之间有什么区别blocking(Future(blockingCall()))?这两个都在中定义scala.concurrent._

我已经查看了scala文档和其他一些堆栈溢出的答案,但仍然不清楚它们的区别.

Mic*_*jac 23

blocking充当ExecutionContext它包含阻塞代码的提示,以便它可以产生一个新线程来防止死锁.这假设ExecutionContext可以做到这一点,但并非所有人都这样做.

让我们一个一个地看一下.


Future(blocking(blockingCall()))
Run Code Online (Sandbox Code Playgroud)

这需要隐式ExecutionContext执行Future.如果ExecutionContext正在使用的是BlockContext(像是scala.concurrent.ExecutionContext.Implicits.global),它可能能够在其线程池中生成一个新线程来处理阻塞调用(如果需要).如果不是,那么没有什么特别的事情发生.


blocking(Future(blockingCall()))
Run Code Online (Sandbox Code Playgroud)

这告诉我们Future(blockingCall())可能是一个阻塞调用,因此它被视为与上面相同.除此之外,Future.apply是非阻塞的,因此blocking有效地使用除了增加一点开销之外什么都不做.ExecutionContext我们从这里称之为什么并不重要,因为它无论如何都不会阻塞.然而,在阻塞调用Future将阻止在一个线程ExecutionContext运行它的,提示其阻断.所以,没有理由这样做.

我已经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)) }
Run Code Online (Sandbox Code Playgroud)

  • 它也不是关键字,它只是一种方法. (2认同)