Scala期货如何在线程上运行?以及如何将它们用于执行异步和非阻塞代码?

alt-f4

据我了解,在Scala中有3种执行IO的方法,我将尝试用伪代码来表达。

,同步与阻塞:

val syncAndBlocking: HttpResponse = someHttpClient.get("foo.com")

在这里,主线程只是空闲,直到响应返回。

其次,异步但仍处于阻塞状态:

val asyncButBlocking: Future[HttpResponse] = Future { someHttpClient.get("bar.com") }

据我了解,这里的主线程是空闲的(因为Future在单独的线程上执行),但是该单独的线程被阻塞了。

第三,异步和非阻塞。我不确定如何实现该功能,但我最好猜想该实现(例如,http客户端)本身必须是非阻塞的,因此类似:

val asynAndNotBlocking: Future[HttpResponse] = Future { someNonBlockingHttpClient.get("baz.com") }

我的问题是:

  1. 我的上述假设有效吗?
  2. Scala期货是在OS线程还是在绿色线程上运行?还是取决于执行上下文?
  3. 在IO是异步和非阻塞的第三种情况下,它如何在后台运行?线程是否仅启动任务(例如,发送获取请求),然后再次变为空闲,直到响应到达时通过某种事件循环通知它?

由以下参考文献启发的问题:此处此处

列维·拉姆西(Levi Ramsey)
val syncAndBlocking: HttpResponse = someHttpClient.get("foo.com")

这将阻塞调用线程,直到收到响应为止(如您所述)。

val asyncButBlocking: Future[HttpResponse] = Future { someHttpClient.get("bar.com") }

与对的任何调用一样Future.apply(至少在概念上,可能有一些优化可以消除某些步骤):

  1. 创建一个Function0[HttpResponse](我称之为一个thunk,为了简洁),其apply方法someHttpClient.get("bar.com")如果someHttpClient是静态的,那么理论上这可能会在编译时发生(我不知道Scala编译器是否会执行此优化),否则会在运行时发生。
  2. 将重击传递给Future.apply,然后:
  3. 创建一个Promise[HttpResponse]
  4. ExecutionContext传递的任务隐式调度Future.apply这个任务就是调用thunk:如果thunk成功执行,则与th的结果将成功完成Promise的关联Future,否则,throw会Future失败(也将是完成)Throwable(仅当Throwable匹配时匹配才能失败)通过NonFatal,我太懒了,无法检查,在这种情况下,致命的错误会被捕获ExecutionContext
  5. 一旦在上安排了任务ExecutionContext(执行重击之前可能会或可能不会安排任务),就会返回Future关联的任务Promise

如何执行thunk的细节取决于ExecutionContextScala运行时的细节(对于扩展,取决于Scala运行时的细节)(对于JVM上的Scala,thunk将在所确定的线程上运行ExecutionContext,无论是OS线程还是绿色线程)线程依赖于JVM,但是OS线程可能至少现在是一个安全的假设(Project Loom可能会影响到这一点);对于ScalaJS(因为JavaScript不公开线程)和Scala Native(据我所知:)一个ExecutionContext可以利用操作系统的线程,但会在周围的事物,喜欢GC运行风险),这可能是一个事件循环与全局线程)。

在执行步骤5之前,调用线程一直处于阻塞状态,因此从调用者的角度来看,它是非阻塞的,但是某个地方有一个线程被阻塞。

val asynAndNotBlocking: Future[HttpResponse] = Future { someNonBlockingHttpClient.get("baz.com") }

......是可能不会类型检查(假设它是相同的HttpResponse类型如以上),因为以无阻塞的HttpResponse将不得不被包裹在其表示异步/不阻断(例如,类型Future),所以asyncAndNotBlocking是type Future[Future[HttpResponse]],在一些特定用例之外是一种无意义的类型。您更有可能会遇到以下情况:

val asyncAndNotBlocking: Future[HttpResponse] = someNonBlockingHttpClient.get("baz.com")

或者,如果someNonBlockingHttpClient不是Scala的本机,并且返回其他一些异步库,您将拥有

val asyncAndNotBlocking: Future[HttpResponse] = SomeConversionToFuture(someNonBlockingHttpClient.get("baz.com"))

SomeConversionToFuture基本上类似于上面的草图Future.apply,但是可以代替ExecutionContext在其他异步库中使用use操作来运行代码以在完成Future.get完成关联

如果您确实Future[Future[HttpResponse]]出于某种原因想要,考虑到someNonBlockingHttpClient返回的速度可能非常快.get(请记住,它是异步的,因此它可以在设置请求并计划发送后尽快返回),Future.apply这可能不是解决之道关于事情:步骤1-5的开销可能比花费的时间更长.get对于这种情况,Future.successful很有用:

val doubleWrapped: Future[Future[HttpResponse]] = Future.successful( someNonBlockingHttpClient.get("baz.com"))

Future.successful不涉及重击,创建Promise或安排任务ExecutionContext(甚至不使用ExecutionContext!)。它直接构造一个已经成功完成的Future,但是其中包含的值FutureFuture.successful在调用之前计算的(即执行thunk中的操作)并阻塞了调用线程。如果所讨论的代码阻塞了足够长的时间以设置某些内容以异步执行,那么这不是问题,但是它可以使长时间阻塞的内容像异步/非阻塞一样向外界展示。

知道何时使用Future.applyFuture.successful具有某些重要性,尤其是在您关心性能和可伸缩性时。Future.successful比起不恰当使用,可能更常见Future.apply(因为它不需要隐式ExecutionContext,我看过新手喜欢它)。就像科林·布雷克(Colin Breck)所说的那样,请勿通过不当使用来阻碍您未来的成功Future.successful

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

了解ArrayList以及如何将它们用于TUI

来自分类Dev

如何将异步代码与非阻塞代码接口

来自分类Dev

非阻塞异步mongo java / scala驱动程序可以阻塞线程-如何处理?

来自分类Dev

如何在线程上运行成员函数?

来自分类Dev

当JavaScript是单线程语言时,如何在JavaScript中实现异步无阻塞代码?

来自分类Dev

如何异步和在线程中执行大量的sql查询

来自分类Dev

如何创建用于猪拉丁和嘶嘶声翻译的代码以及同时应用它们的代码?

来自分类Dev

如何在Scrapy / Twisted中使用线程,即如何在响应回调中异步调用阻塞代码?

来自分类Dev

如何在数组上运行循环,组合结果并将它们设置为变量

来自分类Dev

如何在Android中的非UI线程上执行延迟

来自分类Dev

如何在scala中顺序执行期货

来自分类Dev

阻塞与非阻塞异步代码

来自分类Dev

如何在Java(netbeans)中将图标的图像放在哪里?如何将它们链接到代码?

来自分类Dev

如何在Java(netbeans)中将图标的图像放在哪里?如何将它们链接到代码?

来自分类Dev

如何将此代码转换为非阻塞和无锁的?

来自分类Dev

如何将css应用于将它们悬停在其中的三个不同的类上

来自分类Dev

如何在一个函数中运行 2 个异步代码并转义它们?

来自分类Dev

有界上下文和EF代码优先-如何将它们放在一起?

来自分类Dev

如何在循环中执行异步代码?

来自分类Dev

如何在线程之间共享非发送对象?

来自分类Dev

如何在线程之间共享非发送对象?

来自分类Dev

什么是包含集成测试以及如何将它们设置

来自分类Dev

将文件中的值加载到列表中以及如何将它们分离

来自分类Dev

如何在线程池中运行spring-batch作业?

来自分类Dev

如何在线程中运行的函数中设置超时

来自分类Dev

非阻塞代码执行

来自分类Dev

Rich代码段(html)的新功能,如何将它们放入代码中?

来自分类Dev

如何异步执行代码而不创建新线程

来自分类Dev

如何将阻塞代码重构为对node.js非阻塞

Related 相关文章

  1. 1

    了解ArrayList以及如何将它们用于TUI

  2. 2

    如何将异步代码与非阻塞代码接口

  3. 3

    非阻塞异步mongo java / scala驱动程序可以阻塞线程-如何处理?

  4. 4

    如何在线程上运行成员函数?

  5. 5

    当JavaScript是单线程语言时,如何在JavaScript中实现异步无阻塞代码?

  6. 6

    如何异步和在线程中执行大量的sql查询

  7. 7

    如何创建用于猪拉丁和嘶嘶声翻译的代码以及同时应用它们的代码?

  8. 8

    如何在Scrapy / Twisted中使用线程,即如何在响应回调中异步调用阻塞代码?

  9. 9

    如何在数组上运行循环,组合结果并将它们设置为变量

  10. 10

    如何在Android中的非UI线程上执行延迟

  11. 11

    如何在scala中顺序执行期货

  12. 12

    阻塞与非阻塞异步代码

  13. 13

    如何在Java(netbeans)中将图标的图像放在哪里?如何将它们链接到代码?

  14. 14

    如何在Java(netbeans)中将图标的图像放在哪里?如何将它们链接到代码?

  15. 15

    如何将此代码转换为非阻塞和无锁的?

  16. 16

    如何将css应用于将它们悬停在其中的三个不同的类上

  17. 17

    如何在一个函数中运行 2 个异步代码并转义它们?

  18. 18

    有界上下文和EF代码优先-如何将它们放在一起?

  19. 19

    如何在循环中执行异步代码?

  20. 20

    如何在线程之间共享非发送对象?

  21. 21

    如何在线程之间共享非发送对象?

  22. 22

    什么是包含集成测试以及如何将它们设置

  23. 23

    将文件中的值加载到列表中以及如何将它们分离

  24. 24

    如何在线程池中运行spring-batch作业?

  25. 25

    如何在线程中运行的函数中设置超时

  26. 26

    非阻塞代码执行

  27. 27

    Rich代码段(html)的新功能,如何将它们放入代码中?

  28. 28

    如何异步执行代码而不创建新线程

  29. 29

    如何将阻塞代码重构为对node.js非阻塞

热门标签

归档