Iteratees对于管理资源是安全的吗?



假设我正在读取InputStream

我通常怎么做:

val inputStream = ...
try {
    doStuff(inputStream)
} finally {
    inputStream.close()
}

无论doStuff是否抛出异常,我们都将关闭InputStream


如何使用iteratees:

val inputStream ...
Enumerator.fromStream(inputStream)(Iteratee.foreach(doStuff))

InputStream将被关闭(即使doStuff抛出异常)?

一个小测试:

val inputStream = new InputStream() { // returns 10, 9, ... 0, -1
    private var i = 10
    def read() = {
       i = math.max(0, i) - 1
       i
    }
    override def close() = println("closed") // looking for this
}
Enumerator.fromStream(inputStream)(Iteratee.foreach(a => 1 / 0)).onComplete(println)

我们只看到:

Failure(java.lang.ArithmeticException: / by zero)

流从未关闭。将1 / 0替换为1 / 1,您将看到流关闭。

当然,我可以维护对原始流的引用,并在失败的情况下关闭它,但据我所知,使用iteratees的想法是创建可组合迭代,而不必这样做。


  1. 这是预期行为吗?

  2. 是否有一种方法来使用迭代,使资源总是正确处置?

Iteratees是专门为安全的资源管理而设计的。参见Iteratee IO的第一句话:安全、实用、声明性的输入处理:

Iteratee IO是一种具有精确资源控制的增量输入处理方式。

的想法是,当你的资源只能通过迭代器访问时,拥有资源的代码可以准确地告诉迭代器何时完成对资源的使用,并立即关闭它。另一方面,当迭代是手动管理的(如传统的InputStream),资源的用户负责关闭它。这可能导致泄漏。

说,有一个bug在Play 2.1 fromStream没有管理关闭其底层InputStream !此错误已在Play 2.2中修复。

您可以查看fromStream代码,以了解Enumerator是如何通过使用onDoneEnumerating在被迭代者完成时关闭资源来修复的。

相关内容

  • 没有找到相关文章

最新更新