Scala Future并发问题

时间:2016-10-21 11:10:35

标签: multithreading scala

以下是我同时运行任务的课程。我的问题是,即使在获得所有功能的结果后,我的应用程序也永远不会结束。我怀疑线程池没有关闭,这导致我的应用程序即使在我的任务之后还活着。请告诉我,我用谷歌搜索了很多但没有运气。我在这里缺少什么?

 import scala.concurrent.ExecutionContext.Implicits.global
    import scala.concurrent.Future
    import scala.collection.mutable.ListBuffer
    import scala.util.Failure
    import scala.util.Success

    object AppLauncher{

      def launchAll(): ListBuffer[Future[String]] = {
        // My code logic where I launch all my threads say 50
        null
      }

def main(args:Array[String]):Unit= {
register(launchAll())
}



      def register(futureList: ListBuffer[Future[String]]): Unit =
        {
          futureList.foreach { future =>
            {
              future.onComplete {
                case Success(successResult) => {
                  println(successResult)
                }
                case Failure(failureResult) => { println(failureResult) }
              }
            }
          }
        }
    }

2 个答案:

答案 0 :(得分:0)

通常情况下,当您使用Future的可迭代时,您应该使用Future.sequence更改,例如Seq[Future[T]]Future[Seq[T]]

所以,使用类似的东西:

def register(futureList: Seq[Future[String]]) = Future.sequence(futureList) foreach { results =>
  println("received result")
}

如果您想要在完成后映射每个未来并打印输出,您也可以执行以下操作;

def register(futureList: Seq[Future[String]]) = Future.sequence (
  futureList.map(f => f.map { v =>
    println(s"$v is complete")
    v
  }) ) map { vs =>
  println("all values done $vs")
  vs
}

答案 1 :(得分:-1)

最后我能够找出问题。问题是因为线程池即使在我的期货成功完成后也没有终止。我尝试通过稍微改变我的实现来隔离问题。

  

// import scala.concurrent.ExecutionContext.Implicits.global

  import scala.concurrent.Future
  import scala.collection.mutable.ListBuffer
  import scala.util.Failure
  import scala.util.Success

  //Added ExecutionContex explicitly 
  import java.util.concurrent.Executors
  import concurrent.ExecutionContext

  object AppLauncher {

    //Implemented EC explicitly 
    private val pool = Executors.newFixedThreadPool(1000)
    private implicit val executionContext = ExecutionContext.fromExecutorService(pool)

    def launchAll(): ListBuffer[Future[String]] = {
      // My code logic where I launch all my threads say 50
      null
    }

    def main(args: Array[String]): Unit = {
      register(launchAll())
    }

    def register(futureList: ListBuffer[Future[String]]): Unit =
      {
        futureList.foreach { future =>
          {

            println("Waiting...")
            val result = Await.result(future, scala.concurrent.duration.Duration.Inf)

            println(result)

          }

        }
        pool.shutdownNow()
        executionContext.shutdownNow()
        println(pool.isTerminated() + " Pool terminated")
        println(pool.isShutdown() + " Pool shutdown")

        println(executionContext.isTerminated() + " executionContext terminated")
        println(executionContext.isShutdown() + " executionContext shutdown")
      }

  }

将突出显示的代码添加到关闭池之前的结果

  

false池终止

     

true Pool shutdown

     

false executionContext终止

     

true executionContext shutdown

添加突出显示的代码后解决了我的问题。我确保我的代码中没有资源泄漏。我的场景允许我在所有期货完成时杀死池。我知道我将优雅的回调实现改为阻塞实现,但它仍然解决了我的问题。