当前位置: 首页 > 知识库问答 >
问题:

平面图期货列表的期货正在执行阻塞操作,那么为什么不将代码包含在阻塞{...}中呢?

孙莫希
2023-03-14

在完成Coursera课程中关于反应式编程的一些练习和视频时,我看到了一个方法的定义,该方法可以“排序”未来的列表。该方法返回一个未来,它将完成等待fts中所有期货的工作(见下面的代码),并将这些结果打包到一个列表[T],当按顺序返回的将来[List[T]完成时,该列表将可用。

def sequence[T](fts: List[Future[T]]): Future[List[T]] = {
    fts match {
        case Nil => Future(Nil)
        case (ft::fts) => ft.flatMap(t => sequence(fts)
            .flatMap(ts => Future(t::ts)))
    }
}

这个代码是老师给的,所以我猜它应该代表了如何做这种事情的最佳模式。然而,在讲座的其他地方,老师们说:

每当有长时间运行的计算或阻塞时,请确保在阻塞构造中运行它。例如:

    blocking {
      Thread.sleep(1000)
    } 

用于将一段代码指定为潜在的阻塞。具有阻塞构造的异步计算通常被调度在单独的线程中以避免潜在的死锁。例如:假设您有一个未来f,它等待计时器或资源或监视器条件,该条件只能由其他未来g满足。在这种情况下,f中执行等待的代码部分应该包装在阻塞中,否则未来g可能永远不会运行。

现在…我不明白的是为什么“匹配”表达式没有包装在“阻塞”表达式中。难道我们不希望所有的平面映射都(潜在地)花费大量的时间吗?

附注:scala.concurrent.Future 类中有一个“官方”序列方法,该实现也不使用阻塞。

我也会把它发布到Coursera论坛,如果我得到回复,我也会在这里发布。


共有1个答案

慕容劲
2023-03-14
匿名用户

难道我们不期望所有的平面图都需要(潜在的)相当长的时间吗?

不。flatMap只是构建了一个新的未来,并立即返回。它不会阻塞。

请参阅平面图的默认实现。这是它的简化版本:

trait Future[+T] {

  def flatMap[S](f: T => Future[S])
                (implicit executor: ExecutionContext): Future[S] = {

    val promise = new Promise[S]()

    this.onComplete {

      // The first Future (this) failed
      case Failure(t) => promise.failure(t)

      case Success(v1) =>

        // Apply the flatMap function (f) to the first Future's result
        Try(f(v1)) match {

          // The flatMap function (f) threw an exception
          case Failure(t) => promise.failure(t)

          case Success(future2) =>
            future2.onComplete {

              // The second Future failed
              case Failure(t) => promise.failure(t)

              // Both futures succeeded - Complete the promise
              // successfully with the second Future's result.
              case Success(v2) => promise.success(v2)
            }
        }
    }
    promise.future
  }
}

当您调用(平面图)时发生的事情的概述:

    < li >创建promise < li >向此未来添加回拨 < li >兑现promise

该方法返回一个< code>Future,它将完成等待所有未来的工作

我认为这种描述有些误导。您从Future.sequence中获得的Future并不真正“工作”。正如您在上面的代码中看到的,您从平面图中获得的Future(因此您从Future.sequence中获得的Future)只是一个最终将由其他东西完成的promise。唯一真正做任何事情的是执行上下文Future只是指定要做什么。

 类似资料:
  • Java Future对象用于获取由并行线程(执行器)执行的异步计算的结果。我们调用Future.get()方法并等待结果就绪。此示例显示了一种从Future检索结果的非阻塞方式。java实现java非阻塞未来。 在本例中,在并行执行完成后调用onSuccess()方法。问题在于onSuccess()方法未在主线程上运行。我想在主线程上执行onSuccess()方法。我怎样才能解决这个问题。谢谢

  • 如另一个问题中所述,当使用Undertow时,所有处理都应该在专用的工作线程池中完成,如下所示: 我知道可用于显式地告诉Undertow在专用的线程池中调度请求以阻止请求。我们可以通过将包装在实例中来修改上面的示例,如下所示: 调用此方法将exchange置于阻塞模式,并创建一个BlockingHttpExchange对象来存储流。当交换处于阻塞模式时,输入流方法变得可用,除了阻塞和非阻塞模式之间

  • blpop key1...keyN timeout 从左到右扫描返回对第一个非空list进行lpop操作并返回,比如blpop list1 list2 list3 0 ,如果list不存在list2,list3都是非空则对list2做lpop并返回从list2中删除的元素。如果所有的list都是空或不存在,则会阻塞timeout秒,timeout为0表示一直阻塞。当阻塞时,如果有client对ke

  • OpenResty 的诞生,一直对外宣传是同步非阻塞(100% non-blocking)的。基于事件通知的 Nginx 给我们带来了足够强悍的高并发支持,但是也对我们的编码有特殊要求。这个特殊要求就是我们的代码,也必须是非阻塞的。如果你的服务端编程生涯一开始就是从异步框架开始的,恭喜你了。但如果你的编程生涯是从同步框架过来的,而且又是刚刚开始深入了解异步框架,那你就要小心了。 Nginx 为了减

  • 问题内容: 我应该开发一个简单的SFTP。 一切都进行得很好,直到我(在本例中)没有编写全部为止。可以请我解释一下,为什么系统挂在我身上吗? 服务器端: 客户端: 问题答案: 您的循环一直运行到流结束,但是对等方永远不会关闭套接字。该协议似乎要求打开套接字以供其他命令使用,因此您必须调整它的这一部分以包括一个长度字前缀,以便您知道要复制多少字节。 问题不是关于不写所有字节,而是关于阻塞in 。

  • 本文向大家介绍了解节点中代码执行的阻塞和解除阻塞,包括了了解节点中代码执行的阻塞和解除阻塞的使用技巧和注意事项,需要的朋友参考一下 现在,我们在fs模块中具有文件写入功能writeFileSync,如下所示- 同步表示已同步。这是一个阻塞代码示例。一旦文件写入完成,则仅对其余文件执行代码。上面的代码比较简单,但是如果我们进行大量的文件处理操作,将会导致应用性能下降。 这种代码执行方式将减慢其他请求