Why are Futures within Futures running sequentially when started on Akka Dispatcher

后端 未结 3 1916
野趣味
野趣味 2021-01-02 19:59

We observed a strange behavior when we tried to start a number of futures from within an actor\'s receive method. If we use our configured dispatchers as ExecutionContext,

3条回答
  •  再見小時候
    2021-01-02 20:25

    After some research I found out that the Dispatcher class implememts akka.dispatch.BatchingExecutor. For performance reasons, this class checks which tasks should be batched on the same thread. Future.map internally creates a scala.concurrent.OnCompleteRunnable which is batched in the BatchingExecutor.

    This seems to be reasonable for map() / flatMap() where one task generates one subsequent task, but not for explicit new Futures which are used to fork work. Internally, Future.apply is implemented by Future.successful().map and is thus batched. My workaround is now to create futures in a different way:

    object MyFuture {
      def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = {
        val promise = Promise[T]()
        class FuturesStarter extends Runnable {
          override def run(): Unit = {
            promise.complete(Try(body))
          }
        }
        executor.execute(new FuturesStarter)
        promise.future
      }
    }
    

    The FutureStarter-Runnables are not batched and thus run in parallel.

    Can anybody confirm that this solution is okay? Are there better ways to resolve this issue? Is the current implementation of Future / BatchingExecutor wanted, or is it a bug?

提交回复
热议问题