Scala 如何产生未知数量的未来,并在一个或多个失败的情况下合并结果?
我想将下面的顺序代码转换为具有未来的并发代码,并需要关于如何构造它的建议 顺序:Scala 如何产生未知数量的未来,并在一个或多个失败的情况下合并结果?,scala,future,Scala,Future,我想将下面的顺序代码转换为具有未来的并发代码,并需要关于如何构造它的建议 顺序: import java.net.URL val providers = List( new URL("http://www.cnn.com"), new URL("http://www.bbc.co.uk"), new URL("http://www.othersite.com") ) def download(urls: URL*) = urls.flatMap(url => io.Sour
import java.net.URL
val providers = List(
new URL("http://www.cnn.com"),
new URL("http://www.bbc.co.uk"),
new URL("http://www.othersite.com")
)
def download(urls: URL*) = urls.flatMap(url => io.Source.fromURL(url).getLines).distinct
val res = download(providers:_*)
我想下载通过下载方法的varargs输入的所有源代码,并将结果合并到一个Seq/List/Set中,不管是什么。当一个未来失败时,比如说因为服务器不可访问,它应该继续运行并返回结果firstCompletedOf不起作用,因为我需要所有结果,只有一个由于错误而失败。我曾想过使用如下所示的Future.sequence,但我无法让它工作。这是我试过的
def download(urls: URL*) = Future.sequence {
urls.map { url =>
Future {
io.Source.fromURL(url).getLines
}
}
}
这将生成一个Seq[Future[Iterator[String]]],它与M_u3;[Future[a_3;]]不兼容
我想要的是未来的[迭代器[字符串]]。(我想我返回了一个迭代器,因为我以后需要用迭代器上的reset方法重用它。)您可以使用:
或者,如果您希望非阻塞版本具有未来
:
def download(urls: URL*) = Future {
blocking {
urls.par.flatMap(url => {
Try {
io.Source.fromURL(url).getLines
} match {
case Success(e) => e
case Failure(_) => Seq()
}
})
}
}
val res: Future[Seq[String]] = download(providers:_*)
您想将迭代器[String]作为URL的展平结果吗?未来的示例不是非阻塞的,它只是异步的。@ViktorKlang下载方法是非阻塞的。通过
io.Source.fromURL
获取过程。是同步的。这里根本没有“异步”。发送HTTP请求是一种自然的异步操作,这里根本不需要线程,但OP就是这样使用的。download
是异步的,因为它将在工作执行之前返回(将来)。由于Future.apply的工作需要调用一个阻塞方法(fromURL(…).getLines),这意味着如果ExecutionContext同步运行,那么该方法将阻塞调用者,否则它将阻塞执行逻辑的线程。因此,它不是非阻塞的(某些线程将被阻塞),它是异步的,可能是并发的,并且使用并行化结构。(免责声明:我是Scala标准库中Scala Futures的主要作者)@ViktorKlang我知道你是谁:)<代码>下载是“伪异步”。它使用阻塞方法fromURL
来执行本质上是异步的工作,就像通过线路发送请求一样。它对使用者来说是非阻塞的,但在内部它使用一个ExecutionContext线程来阻塞它实际上不应该阻塞的工作。我们之前在twitter上讨论过:),我说Java/Scala缺少一个告诉调用方“这实际上是一个IO完成”的结构。不,它不是“伪异步”:它要么同步执行(sync EC,高度不鼓励),要么异步执行(在工作完成之前返回)。如果前者阻止调用线程,如果后者阻止EC线程。不管怎样,它都会阻止某些内容:)
def download(urls: URL*) = Future {
blocking {
urls.par.flatMap(url => {
Try {
io.Source.fromURL(url).getLines
} match {
case Success(e) => e
case Failure(_) => Seq()
}
})
}
}
val res: Future[Seq[String]] = download(providers:_*)