我试图在实际代码中模拟我的情况 .

用例很简单:有:

Future {blocking { 
   // in there it calls nested futures    
 }}

更详细的(全局执行上下文用作父级,但有一个尝试使用separete one for children):

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秒内完成工作,因为如果我们没有孩子的话 . 此外,我希望看到两个连接池而不是一个 .

问:实现这一目标的建议是什么?

UPDATE: 我想这完全是关于基于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.

如果我希望父母独立于孩子,反之亦然,那么我是不是应该使用那个 global 背景? ( funny how many people in Internet are playing with global only . )

说我知道ma app有20 000个客户端,每个客户端总是进行1-100秒长的操作(op1-> op1.op1) . 然后我就可以将一个执行上下文用于20 000个连接池(最大值) . 和所有类型的长时间运行操作所需的执行上下文一样多(父级 - >子级未向父级报告的子级) . 说: printingExConlogExConreadStufExConwriteStuffExCon

但是,如果我知道一个oparation应该包括anoter one并且他们可能加入然后(仅)我可以使用那个全局Ex上下文?

否则,如果我将使用 global ex context作为上下文 - 所有人都会加入它并且我最终会遇到性能问题,我在本周日开始时解释了这个问题 .

UPDATE: 我浪费了很多时间试图理解为什么修复版本(传递给childPlay的Future {}(ex)的'ex'产生了一个忽略睡眠的行为,并且在许多其他情况下表现得很好 . 问题是在代替运行/ buildng时修复的在IntellyJIDEA 14(按CTRL-SHIFT F10)i build it wit sbt 运行..