4

这按预期工作:

object Planexecutor extends App {    
  import scalaz.concurrent.Future
  import scala.concurrent.duration._

  val f = Future.apply(longComputation)
  val result = f.run
  println(result)
}

这不会:

object Planexecutor extends App {    
  import scalaz.concurrent.Future
  import scala.concurrent.duration._

  val f = Future.apply(longComputation).timed(1.second)
  val result = f.run
  println(result)
}

在第一种情况下,应用程序正常退出,而在第二种情况下则不会。但是,两个版本都正确打印出结果值。

这是一个错误还是我不理解的东西?

4

1 回答 1

5

问题在于正在使用的线程池timed。如果您查看源代码,您可以看到它使用的默认值Strategy.DefaultTimeoutScheduler只是一个通用的 java 线程池,并且它的线程没有设置为守护进程状态。默认Future.apply的线程池确实在其线程上设置了守护程序状态,因此 JVM 将正确关闭。要解决此问题,您可以在代码完成后手动关闭线程池:

  scalaz.concurrent.Strategy.DefaultTimeoutScheduler.shutdown()

或者你可以传递一个不同的线程池:

  val newTimeOutScheduler = Executors.newScheduledThreadPool(1, new ThreadFactory {
    val defaultThreadFactory = Executors.defaultThreadFactory()
    def newThread(r: Runnable) = {
      val t = defaultThreadFactory.newThread(r)
      t.setDaemon(true)
      t
    }
  })

  val f = Future.apply(longComputation).timed(1.second)(newTimeOutScheduler)

您也可以通过隐式管理它,因此您不必手动添加:

  implicit val newTimeOutScheduler = Executors.newScheduledThreadPool(1, new ThreadFactory {
    val defaultThreadFactory = Executors.defaultThreadFactory()
    def newThread(r: Runnable) = {
      val t = defaultThreadFactory.newThread(r)
      t.setDaemon(true)
      t
    }
  })

  val f = Future.apply(longComputation).timed(1.second)

更新: 这是一个非常简单的修复,所以我提出了拉取请求。

于 2014-09-16T23:37:09.510 回答