我正在为基于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?
答案 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可能会产生一些危险的错误,因为必须非常小心以避免死锁或产生太多线程。