我试图用实际代码模拟我的情况。
用例很简单: 有:
Future {blocking {
// in there it calls nested futures
}}
更详细(全局执行上下文用作父项,但有些人试图将separete用于子项):
object ExContexts {
val main = scala.concurrent.ExecutionContext.Implicits.global
val ecChildren = scala.concurrent.ExecutionContext.fromExecutor(Executors.newFixedThreadPool(1))
}
object NestedFutures2 extends App {
import scala.concurrent.ExecutionContext.Implicits.global
val cores = Runtime.getRuntime.availableProcessors
val works = parentWork(ExContexts.main) // main EC
val result1: Seq[Seq[Future[String]]] = Await.result(Future.sequence(works), Duration.Inf)
println("parents are done their work")
val result2: Seq[String] = Await.result(Future.sequence(result1.flatten), Duration.Inf)
// ---
def parentWork(ex:ExecutionContext): Seq[Future[Seq[Future[String]]]] = {
val works: Seq[Future[Seq[Future[String]]]] =
(1 to cores * 2) map { x =>
Future {
blocking { // will create new thread/place if needed
val parentName = Thread.currentThread.getName
println("parent: " + parentName + " started an action")
val playFutureOutcomes: Seq[Future[String]] = (1 to 10) map {stuffId =>
childPlay(parentName = parentName)(ExContexts.ecChildren)
}
Thread.sleep(1000)
println(s"[${timeStamp()}] parent: " + parentName + " has finished the action")
playFutureOutcomes
}
}
}
works
}
def childPlay(parentName:String)(ex:ExecutionContext):Future[String] = {
Future {
Thread.sleep(2000) // two seconds play session
val threadName = Thread.currentThread.getName
// log
println("child: " + threadName + " of " + parentName + " parent")
Thread.currentThread.getName
}
}
def timeStamp(pattern:String = "ss:mm : hh"): String = {
val fmt = DateTimeFormat.forPattern(pattern)
fmt.print(DateTime.now)
}
}
从输出(8个parrent期货中的5个完成)我看到孩子们利用父母线程...:
[01:31 : 05] parent: ForkJoinPool-1-worker-5 has finished the action
[01:31 : 05] parent: ForkJoinPool-1-worker-11 has finished the action
[01:31 : 05] parent: ForkJoinPool-1-worker-1 has finished the action
[01:31 : 05] parent: ForkJoinPool-1-worker-3 has finished the action
[01:31 : 05] parent: ForkJoinPool-1-worker-7 has finished the action
child: ForkJoinPool-1-worker-13 of ForkJoinPool-1-worker-1 parent
child: ForkJoinPool-1-worker-5 of ForkJoinPool-1-worker-5 parent
child: ForkJoinPool-1-worker-1 of ForkJoinPool-1-worker-1 parent
child: ForkJoinPool-1-worker-11 of ForkJoinPool-1-worker-11 parent
child: ForkJoinPool-1-worker-3 of ForkJoinPool-1-worker-3 parent
child: ForkJoinPool-1-worker-7 of ForkJoinPool-1-worker-7 parent
child: ForkJoinPool-1-worker-13 of ForkJoinPool-1-worker-11 parent
...
我希望父母一个人能在1秒钟内完成工作,因为如果我们没有孩子的话。此外,我希望看到两个连接池而不是一个。
问:获得它的建议是什么?更新 我想这是基于Implicit.glocal构建的Join-Pool。所有嵌套的Furue都将连接到一个池?
// What (I think) I see is that if we have 'global' execution context as parent/main,
// then whatever we pass as execution context to the child Future still will use global context
// and still will be using ONE connection pool.
// And then therefore wll have performance problem if children do not use 'blocking' -
// parents will be stuck in cores-long connection pool
// So: Children will 'inherit' execution context, but not 'blocking'
// and as children connected/joined to the execution context the parents will not be able to do
// anything about it but wait for the free space in the pool (when child is done)
// new additional threads will not be creating for the next parent because (i guess)
// Global execution context will not see the reason of/for it.
// Like a snapshot of the moment of time:
// Connection Pool: [ch1, ch2, ch3, p1]
// It things:Ok there is one parent (p1) in the pool if one more parent
// future will come I create for it new thread it the pool.
// But because we have more joined children than parents in the list
// the moment when Global ex context can help parent will never come.
如果我希望父母独立于childrent,反之亦然,那么我是否应该使用全局上下文? (有趣的是,互联网上有多少人只玩全球。)
说我知道ma app有20 000个客户端,每个客户端总是进行1-100秒长的操作(op1-> op1.op1)。然后我就可以将一个执行上下文用于20 000个连接池(最大值)。和所有类型的长期运行所需的执行上下文一样多(父级 - >子级,其中子级未向父级报告)。说:printingExCon
,logExCon
,readStufExCon
,writeStuffExCon
但是,如果我知道一个oparation应该包括anoter one并且他们可能加入然后(仅)我可以使用那个全局Ex上下文?
否则,如果我使用全局 ex上下文作为人工上下文 - 所有人都会加入它并且我最终会遇到性能问题,我在本周日开始时解释了这个问题。
更新 我浪费了很多时间试图理解为什么修复版本('ex'传递给childPlay的Future {}(ex)产生的输出忽略了睡眠并且在许多其他情况下表现得很好。问题是修复而不是运行/在IntellyJIDEA 14中构建(按CTRL-SHIFT + F10)我构建它有机会运行..