微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Scala Future.sequence(Iterator) 抛出 NoSuchElementException

如何解决Scala Future.sequence(Iterator) 抛出 NoSuchElementException

为什么下面的代码会抛出java.util.NoSuchElementException: next on empty iterator???

     implicit val ec = ExecutionContext.global
     val it = (0 until 10).toIterator.map{
       x =>
         Thread.sleep(500)
         println(x)
         x
     }
     val it2 = new Iterator[Future[Int]] {
       def hasNext = it.hasNext
       def next() = Future { blocking { it.next() } }
     } //This should be equivalent to it.map{x => Future{blocking{x}}}
     Await.result(Future.sequence(it2),Inf)

辅助问题:为什么 it2 的行为不像 it.map{x => Future{blocking{x}}} ??

解决方法

您有一个并发错误,有人调用 hasNext 它返回 true 因为底层迭代器能够生成新元素。然后它调用 next 这将返回一个未来,完成后将保存 next 值。
但是,对于调用者 (在本例中为 Future.sequence 它已经完成,因此它再次调用 hasNext 将再次返回 true 但因为底层迭代器没有t 完成了第一个元素的生成,所以我们生成了第二个元素,直到第一个元素完成(这样你就不会赢得未来)

这会继续创建越来越多的期货,最终将调用 next 并获得 NoSuchElementException,因为底层迭代器没有更多元素,但您已经创建了越来越多的期货等待越来越多的元素。
所以,换句话说,你在 true 中得到一个 hasNext 只是因为它没有完成生成元素,因此没有改变它的内部状态;不是因为它实际上有更多元素。

这是一个很好的记录,可变性 + 并发性 = 头痛。
同样,我建议您为此使用适当的抽象

,

另一个答案指出了正确的方向,但我只是改写得更干净一点。通过在 next()hasNext 方法中添加一些打印输出,可以看到它们被连续调用。这是因为 itit2 不同步:it.next() 是阻塞的,而 it2.next() 不是,而是 it2.hasNext == it.hasNext,所以 {{1 }} 正在阻塞。结果 it2.hasNextit2next() 不同步,这是一团糟!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?