未来地图(等待)执行上下文。使用FixedThreadPool停止执行

时间:2015-09-12 23:41:27

标签: scala concurrent.futures executioncontext

   // 1 fixed thread

   implicit val waitingCtx = scala.concurrent.ExecutionContext.fromExecutor(Executors.newFixedThreadPool(1))

    // "map" will use waitingCtx

    val ss = (1 to 1000).map {n => // if I change it to 10 000 program will be stopped at some point, like locking forever
      service1.doServiceStuff(s"service ${n}").map{s =>
        service1.doServiceStuff(s"service2 ${n}")
      }
    }

每个doServiceStuff(name:String)需要5秒钟。 doServiceStuff没有隐式ex:执行上下文作为参数,它在内部使用自己的ex上下文,并在其上执行Future {blocking { .. }}

在最后的节目中打印:

took: 5.775849753 seconds for 1000 x 2 stuffs

如果我将1000更改为 10000 ,则添加更多任务:val ss = (1 to 10000)然后程序停止:

  

~17 027行将打印出来(20 000)。不#34;错误"信息   将被打印。不,"采取"消息将被打印

**并且不会再进一步​​处理。

但是,如果我将exContext更改为ExecutionContext.fromExecutor(null: Executor)(全局一个),则会在大约10秒内结束(但通常不会)。

~17249 lines printed
ERROR: java.util.concurrent.TimeoutException: Futures timed out after [10 seconds]
took: 10.646309398 seconds

这就是问题所在 :为什么使用固定的前上下文池会停止而不发送消息,但是对于全局前上下文,它会终止,但会出现错误和消息?

有时......它不可复制。

更新:如果我将游泳池从1增加到N,我确实会看到"ERROR""took"。无论N是多么高 - 它将是错误。

代码在这里:https://github.com/Sergey80/scala-samples/tree/master/src/main/scala/concurrency/apptmpl

here, doManagerStuff2()

1 个答案:

答案 0 :(得分:0)

我想我知道发生了什么。如果你眯着眼睛,你会发现map职责是非常轻量级的:只是开启一个新的未来(因为doServiceStuff是一个未来)。我敢打赌,如果切换到flatMap,行为将会改变,这实际上会使嵌套的未来变平,因此将等待第二次doServiceStuff调用完成。

由于你没有把这些未来弄平,所有等待下游的人都在等待错误的事情,而你却没有抓住它,因为here你放弃了任何服务回报。

更新

好的,我误解了你的问题,虽然我仍然认为嵌套的Future是一个错误。

当我使用10000任务的两个执行程序尝试你的代码时,我在OutOfMemory执行上下文(即ForkJoin任务)中创建线程时得到service,我就是这样做的期望。您使用了任何特定的内存设置吗?

有1000个任务,他们都成功完成。