Scala的未来是否会长期运行而受阻?

Maa*_*mon 1 future akka spray playframework-2.0 executioncontext

到处都可以看到,在执行长时间运行的操作或阻塞操作时,最好使用特殊的Execution上下文。阻止操作,例如访问数据库。我明白为什么。这是为了避免线程饥饿。我们不想让“ 8”个可用线程忙于一些可能最终返回或保持阻塞的阻塞代码。它会严重降低应用程序速度或无限期阻止它。

同时,我想知道如何实现Spray或Play之类的东西。确实,让我们来看看客户端。发送请求后,我们将获得以后的答复。换句话说,请求是异步执行的。顺便说一句,这可能会导致长时间运行。但是,没有什么可以说启动许多请求会导致线程匮乏。因此,我想知道为什么在这种情况下这不是问题。他们有特殊的线程池吗?

我在《学习Scala中的并发编程》一书中提到,在Future中使用“ Blocking {}”语句块可以帮助其调度程序自动产生更多线程。难道是他们处理的方式?

接收请求可以说是一样的,在游戏中我们可以执行一个异步动作。如果要通过此操作访问数据库,则应使用“ Blocking {}”语句块。如何执行该操作是一个特殊的threadPool / ExecutionContext。

我在这里的假设是,它们依赖于hidden.global ExecutionContext。也许我错了。底线是。默认情况下,发出请求是一个漫长的操作,例如在代码中使用spray会如何处理它,从而不会在代码中创建线程饥饿?

我们使用不同的ExecutionContext吗?

编辑:刚刚发现了这个简短的演示文稿,请不要阻塞-如何弄清Akka和Spray的情况,以更好地说明我在这里遇到的问题。

无论如何,我希望能有其他意见

编辑:这是我了解到的使用未来时会发生的事情:

def apply[T](body: =>T): Future[T] = impl.Future(body)  //here I have omitted the implicit ExecutorContext
impl.Future is an implementation of Future trait:

def apply[T](body: =>T)(implicit executor: ExecutionContext): scala.concurrent.Future[T] =
{
  val runnable = new PromiseCompletingRunnable(body)
  executor.prepare.execute(runnable)
  runnable.promise.future
}
Run Code Online (Sandbox Code Playgroud)

PromiseCompletingRunnable如下所示:

class PromiseCompletingRunnable[T](body: => T) extends Runnable {
val promise = new Promise.DefaultPromise[T]()

override def run() = {
  promise complete {
    try Success(body) catch { case NonFatal(e) => Failure(e) }
  }
} } 
Run Code Online (Sandbox Code Playgroud)

摘自:需要澄清Scala中的期货和承诺 我在《学习Scala中的并发编程》一书中写了一些简单而相似的内容

对我来说,这意味着:ThreadPool中有一个Thread,它使该任务出队,并尝试根据该任务的执行结果来设置一个promise future值。如果这是正确的,我看不出执行IO调用的任务不会如何阻止该线程的运行。

Jam*_*per 5

我认为您不了解的是,当您使用阻塞API提出客户端请求时,线程在那里坐着,什么也没做,直到响应返回为止。但是,如果使用异步API,则在等待响应返回时,没有线程在等待。当它回来时,请确保从执行上下文中拉出一个线程来完成工作,但这就是您希望线程执行的工作-工作,而不是什么都不做。使数百个线程不做任何操作来等待客户端请求或数据库查询返回将浪费资源。而且由于它们不是免费的,因此必须加以限制,这就是线程匮乏的原因。在异步框架中,仅在有工作要做时才使用线程。也就是说,如果每个CPU内核只有一个线程,如果耗尽线程池,则意味着CPU利用率为100%,而在阻塞框架中,CPU利用率仅为10%时,线程池就可以耗尽。请记住,大多数普通的Web应用程序将大部分时间都花在IO上,即等待数据库调用或http客户端调用返回。等待量与实际工作量通常相差一个数量级或更大。因此,仅在需要完成工作时才使用线程是一个很大的优势。

  • 首先,非常感谢您提供详细的答案。但是我认为,我理解您之前所说的大部分内容。尽管我认为您的回答中有些夹杂会有所帮助。您说当您使用异步Ali时,没有线程在等待。那是我的问题所在。我想如何运作?因为对我来说,当您拨打该电话时,会创建一个将来的响应。因此,某个地方有一个可运行的库,试图用一些代码的结果来填充承诺。该可运行对象存在于线程中。对我来说,这是一个等待的话题,还是我错了。 (2认同)