是否可以创建自己的ExecutionContext来正确处理scala.concurrent.blocking?

时间:2015-12-19 22:02:42

标签: scala concurrency

我正在为基于ScheduledExecutorService的计时器编写close()方法:

override def close(implicit executionContext: ExecutionContext): Future[Unit] = {
  val p = Promise[Unit]
  executionContext.execute(new Runnable() {
    override def run() = {
      blocking { 
        p complete Try {
          executor.shutdown()
          //OK for default global execution context
          //As we marked this code as blocking, additional thread
          //will be used on that so no threadpool starvation
          executor.awaitTermination(1, TimeUnit.DAYS)
        }
      }
    }
  })
  p.future
}

但是如果我自己实现ExecutionContext,这段代码将阻塞池中的一个线程,因为我没有找到任何方法来获取阻塞上下文。

所以,问题:是否可以创建自己的ExecutionContext来正确处理scala.concurrent.blocking?

1 个答案:

答案 0 :(得分:3)

当然可能,它远非琐碎。您需要创建一个ExecutionContext来创建混合在BlockContext中的线程,这需要以下方法:

def blockOn[T](thunk: => T)(implicit permission: CanAwait): T

blocking(thunk)最终将导致调用blockOn(thunk),而blockOn应该确定ExecutionContext是否已经达到饥饿并且需要做某事。 scala.concurrent.ExecutionContext.Implicits.global执行this way,但正如您所见,它使用ForkJoinPool进行繁重的工作,并且实现 thousands of lines of code

请记住,无论您使用ExecutionContext.Implicits.global还是您自己的`ExecutionContext,您的代码仍会阻止某个帖子。唯一的区别是前者产生另一个线程来处理太多被阻塞的事实。创建自己的bug可能会产生一些危险的错误,因为必须非常小心以避免死锁或产生太多线程。