我正在为基于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?
发布于 2015-12-19 22:33:16
当然,这是有可能的,只是它远不是微不足道的。您需要创建一个ExecutionContext来创建混合在BlockContext中的线程,这需要以下方法:
def blockOn[T](thunk: => T)(implicit permission: CanAwait): Tblocking(thunk)最终将导致调用blockOn(thunk),而blockOn应该知道ExecutionContext是否已经达到饥饿状态,是否需要做一些事情。scala.concurrent.ExecutionContext.Implicits.global完成了这边请,但是正如您所看到的,它使用ForkJoinPool来完成繁重的工作,实现就是https://github.com/scala/scala/blob/1fbce4612c21a4d0c553ea489b4765494828c09f/src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java。
请记住,无论是使用ExecutionContext.Implicits.global还是使用自己的“`ExecutionContext”,线程仍然会被代码阻塞。唯一的区别是前者产生了另一个线程来处理太多被阻塞的事实。但是,创建自己的线程可能会产生一些危险的bug,因为必须非常小心,以避免死锁或产生过多的线程。
https://stackoverflow.com/questions/34375843
复制相似问题