在Scala中,据我所知,ExecutionContext.global
与通常使用ExecutionContext
创建的其他ExecutionContext.fromExecutor(...)
对象不同,因为它可以使用scala.concurrent.blocking
作为信号当最初的小线程池被长时间运行,可能是io-bound计算阻塞时,产生额外的线程。有没有办法创建另一个这样的ExecutionContext
?查看源代码,似乎ExecutionContext.global
以相当独特的方式创建,通过内部调用impl.ExecutionContextImpl.fromExecutor(null: Executor)
,即包私有。
答案 0 :(得分:1)
所以你可以用这个很容易地创建它:
scala.concurrent.ExecutionContext.fromExecutor(null)
它将完成与ExecutionContext.global
完全相同的过程。
在幕后,这只是创建一个ForkJoinPool
,其中包含一个特殊ThreadFactory
来处理scala.concurrent.blocking
信号。如果您想要更多控制权,可以创建自己的ForkJoinPool
,然后提供ThreadFactory
做类似于scala版本的操作(source):
class DefaultThreadFactory(daemonic: Boolean) extends ThreadFactory with ForkJoinPool.ForkJoinWorkerThreadFactory {
def wire[T <: Thread](thread: T): T = {
thread.setDaemon(daemonic)
thread.setUncaughtExceptionHandler(uncaughtExceptionHandler)
thread
}
def newThread(runnable: Runnable): Thread = wire(new Thread(runnable))
def newThread(fjp: ForkJoinPool): ForkJoinWorkerThread = wire(new ForkJoinWorkerThread(fjp) with BlockContext {
override def blockOn[T](thunk: =>T)(implicit permission: CanAwait): T = {
var result: T = null.asInstanceOf[T]
ForkJoinPool.managedBlock(new ForkJoinPool.ManagedBlocker {
@volatile var isdone = false
override def block(): Boolean = {
result = try thunk finally { isdone = true }
true
}
override def isReleasable = isdone
})
result
}
})
}
此外,Akka对FJP
也有启示。