【问题标题】:Closing resource created by timed-out future关闭由超时未来创建的资源
【发布时间】:2015-01-14 03:19:59
【问题描述】:

当我们有创建资源的方法时,有时只需要等待指定的持续时间。例如,我们要等待 10 秒才能连接到数据库。

我尝试使用 future 和 Await.result 来获得它。不幸的是, Await.result 在指定时间后抛出异常,但不会杀死正在进行的未来。因此,在超时之后,我们以 TimeoutException 告终,但如果未来最终完成,我们将无法关闭返回的结果。 示例:

import java.io.Closeable
import java.util.concurrent.TimeoutException

import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.DurationInt
import scala.concurrent.future

object Test {
    object ConnectionManager {
        class Connection extends Closeable {
        println("Connected")
        override def close = println("DB closed")
        }

        def connect = {
        println("Connecting to DB...")
        Thread.sleep(1000 * 7)
        new Connection
        }
    }

    def main(args: Array[String]): Unit = {
        val f = future {
        ConnectionManager.connect
        }
        try {
        val result = Await.result(f, 5 seconds)
        result.close
        } catch {
        case e: TimeoutException => println("Connection timeout")
        }
        Thread.sleep(10 * 1000)
        println("Finished")
    }
}

结果是:

正在连接数据库...

连接超时

已连接

完成

所以连接被创建但从未关闭

【问题讨论】:

  • 如果等待结果超时,为什么还要使用 Future?基本上真正的超时会抛出异常并且永远不会创建连接。
  • 我需要自己提供时间。不是通过外部库。数据库连接只是一个例子。其他示例包括获取网络资源和创建 InputStream。如果连接时间过长,我们希望使此类操作超时。

标签: scala timeout future


【解决方案1】:

您可以将f.onSuccess { case c => c.close } 添加到您的catch 子句中。

【讨论】:

  • 您的解决方案在精神上是正确的,但不会编译。这里的onSuccess 方法采用PartialFunction[Connection,Unit] 而不是Function1[Connection,Unit]。我相信它会像f.onSuccess{case c => c.close}一样工作。
  • 我不会打断未来,但对我来说已经足够接近了。
猜你喜欢
  • 1970-01-01
  • 2018-10-25
  • 1970-01-01
  • 2021-02-23
  • 2013-03-29
  • 2014-08-30
  • 2020-10-09
  • 1970-01-01
  • 2021-12-01
相关资源
最近更新 更多