假设我从一些URL下载了一个(可能很大的)图像列表.我正在使用Scala,所以我要做的是:
import scala.actors.Futures._
// Retrieve URLs from somewhere
val urls: List[String] = ...
// Download image (blocking operation)
val fimages: List[Future[...]] = urls.map (url => future { download url })
// Do something (display) when complete
fimages.foreach (_.foreach (display _))
Run Code Online (Sandbox Code Playgroud)
我对Scala有点新意,所以对我来说这看起来仍然有些神奇:
display _)是否会在主线程上执行,如果没有,我该如何确定呢?谢谢你的建议!
Java Future有一个cancel方法,它可以中断运行Future任务的线程.例如,如果我将一个可中断的阻塞调用包装在一个Java Future我可以稍后中断它.
Scala Future没有提供任何cancel方法.假设我在一个中包含一个可中断的阻塞调用Scala Future.我怎么能打断它?
出于某种原因,我无法解决这个问题.我有一个运行Play的应用程序调用Elastic Search.作为我的设计的一部分,我的服务使用包含scala future的Java API,如本博文中所示.我已经更新了该帖子中的代码以提示ExecutionContext,它将执行一些阻塞I/O,如下所示:
import scala.concurent.{blocking, Future, Promise}
import org.elasticsearch.action.{ActionRequestBuilder, ActionListener, ActionResponse }
def execute[RB <: ActionRequestBuilder[_, T, _, _]](request: RB): Future[T] = {
blocking {
request.execute(this)
promise.future
}
}
Run Code Online (Sandbox Code Playgroud)
我构建查询以发送给ES的实际服务将executionContext作为构造函数参数,然后用于调用弹性搜索.我这样做是为了让播放使用的全局执行上下文不会让它的线程被ES的阻塞调用所束缚.这个SO评论提到只有全局上下文才能阻塞,所以这让我不得不创建自己的.在同一个帖子/答案中有很多关于使用ForkJoin池的信息,但是我不确定如何使用这些文档中的内容并将其与阻塞文档中的提示相结合来创建响应阻塞的执行上下文提示.
我认为我遇到的一个问题是,我不确定如何首先如何回应阻止上下文?我正在阅读最佳实践,它使用的示例是一个无限的线程缓存:
请注意,在这里我更喜欢使用无限制的"缓存线程池",因此它没有限制.在阻塞I/O时,我们必须拥有足够的线程来阻止I/O. 但是如果无界限太多,取决于用例,你可以稍后对其进行微调,这个样本的想法是你得到了滚动.
那么这是否意味着我的ForkJoin支持的线程池,我应该尝试在处理非阻塞I/O时使用缓存线程并创建一个新线程来阻止IO?或者是其他东西?几乎我在网上找到的关于使用单独线程池的每个资源都倾向于执行新手指南所做的事情,也就是说:
如何调整各种线程池在很大程度上取决于您的个人应用程序,超出了本文的范围.
我知道这取决于你的应用程序,但在这种情况下,如果我只想创建某种类型的阻塞感知ExecutionContext并理解管理线程的合适策略.如果Context专门用于应用程序的单个部分,那么我应该只是制作一个固定的线程池大小而不是首先使用/忽略该blocking关键字吗?
我倾向于絮絮叨叨,所以我会试着在答案中分解我正在寻找的东西:
blocking那里的关键部分.对不起,这里有一个很长的问题,我只是想让你了解我正在看的东西,并且我一直试图绕过这一天超过一天需要一些外界的帮助.
编辑:为了清楚起见,ElasticSearch Service的构造函数签名是:
//Note that these are not implicit parameters!
class …Run Code Online (Sandbox Code Playgroud) 参考这个被接受的答案中的第三点,是否有任何情况下,blocking对于长时间运行的计算,无论是CPU还是IO绑定,在"a"内执行它都是毫无意义或不好的Future?