scala.concurrent.blocking - 它实际上做了什么?

2024-05-26

我花了一段时间学习 Scala 执行上下文、底层线程模型和并发性的主题。你能解释一下通过什么方式吗scala.concurrent.blocking “调整运行时行为” and “可以提高性能或避免死锁”如中所述scaladoc http://www.scala-lang.org/api/2.11.6/index.html#scala.concurrent.package?

In 文档 http://docs.scala-lang.org/overviews/core/futures.html,它作为一种等待未实现 Awaitable 的 api 的方法呈现。 (也许还应该包装长时间运行的计算?)。

它实际上做了什么?

追踪源码 https://github.com/scala/scala/blob/5e0880fe05fb65a8757721be7e5be6a3259c19a8/src/library/scala/concurrent/package.scala#L54不会轻易泄露它的秘密。


blocking旨在作为一个提示ExecutionContext所包含的代码正在阻塞并可能导致线程饥饿。这将使线程池有机会产生新线程以防止饥饿。这就是这个意思“调整运行时行为”。但这并不神奇,并且不适用于所有情况ExecutionContext.

考虑这个例子:

import scala.concurrent._
val ec = scala.concurrent.ExecutionContext.Implicits.global

(0 to 100) foreach { n =>
    Future {
        println("starting Future: " + n)
        blocking { Thread.sleep(3000) }
        println("ending Future: " + n)
    }(ec)
}

这是使用默认的全局ExecutionContext。按原样运行代码,您会注意到 100Futures 都会立即执行,但是如果删除blocking,他们一次只执行几个。默认ExecutionContext将通过生成新线程对阻塞调用(如此标记)做出反应,因此不会因运行而过载Futures.

现在看一下这个具有 4 个线程的固定池的示例:

import java.util.concurrent.Executors
val executorService = Executors.newFixedThreadPool(4)
val ec = ExecutionContext.fromExecutorService(executorService)

(0 to 100) foreach { n =>
    Future {
        println("starting Future: " + n)
        blocking { Thread.sleep(3000) }
        println("ending Future: " + n)
    }(ec)
}

This ExecutionContext不是为了处理生成新线程而构建的,因此即使我的阻塞代码被blocking,可以看到它仍然最多只执行4Future一次。这就是为什么我们这么说“可以提高性能或避免死锁”——不能保证。正如我们在后者中看到的ExecutionContext,根本无法保证。

它是如何工作的?如链接所示,blocking执行这段代码:

BlockContext.current.blockOn(body)(scala.concurrent.AwaitPermission)

BlockContext.current检索BlockContext从当前线程来看here https://github.com/scala/scala/blob/092690e7bf71bb22e6e57afb7ea7f67fdfe31a0a/src/library/scala/concurrent/BlockContext.scala#L59-65. A BlockContext通常只是一个ThreadBlockContext混合了特征。如源所示,它要么存储在ThreadLocal,或者如果在那里找不到它,则从当前线程中进行模式匹配。如果当前线程不是BlockContext,那么DefaultBlockContext被用来代替。

Next, blockOn被调用当前BlockContext. blockOn是一个抽象方法BlockContext,所以它的实现取决于如何ExecutionContext处理它。如果我们看一下实施DefaultBlockContext https://github.com/scala/scala/blob/092690e7bf71bb22e6e57afb7ea7f67fdfe31a0a/src/library/scala/concurrent/BlockContext.scala#L52-54(当当前线程不是BlockContext),我们看到blockOn实际上那里什么也没做。所以使用blocking在非BlockContext意味着根本没有做任何特殊的事情,并且代码按原样运行,没有副作用。

那么线程呢BlockContext是?例如,在global上下文,所见here https://github.com/scala/scala/blob/092690e7bf71bb22e6e57afb7ea7f67fdfe31a0a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala#L40-56, blockOn做得更多。深入挖掘,您可以看到它使用了ForkJoinPool在引擎盖下,与DefaultThreadFactory在用于生成新线程的同一代码段中定义ForkJoinPool。如果没有实施blockOn来自BlockContext(线程),ForkJoinPool不知道您正在阻塞,并且不会尝试生成更多线程作为响应。

Scala's Await https://github.com/scala/scala/blob/fdb3d96409033ea0b15a37118c423618ac00acb5/src/library/scala/concurrent/package.scala#L148也使用blocking其实施。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

scala.concurrent.blocking - 它实际上做了什么? 的相关文章

  • 简单的 Scala actor 问题

    我确信这是一个非常简单的问题 但很不好意思地说我无法理解它 我有一个 Scala 值列表 我想使用演员来并行地对每个值进行一些 外部 调用 我想等到所有值都已处理完毕 然后继续 没有共享值被修改 有人可以建议吗 Thanks Scala 中
  • 将列表拆分为多个具有固定元素数量的列表

    如何将元素列表拆分为最多包含 N 个项目的列表 例如 给定一个包含 7 个元素的列表 创建 4 个组 最后一组可能包含较少的元素 split List 1 2 3 4 5 6 seven 4 gt List List 1 2 3 4 Lis
  • 如何在Dotty中使用given?

    我在看Dotty下的文档Contextual Abstractions页面 我看到了Given Instances 给定实例 或者简单地 给定 定义了 规范 值 用于合成给定子句的参数的某些类型 例子 trait Ord T def com
  • Java ReentrantReadWriteLocks - 如何在读锁中安全地获取写锁?

    我现在在我的代码中使用可重入读写锁 http java sun com javase 6 docs api java util concurrent locks ReentrantReadWriteLock html同步对树状结构的访问 这
  • Spark RDD默认分区数

    版本 Spark 1 6 2 Scala 2 10 我正在执行以下命令spark shell 我试图查看 Spark 默认创建的分区数量 val rdd1 sc parallelize 1 to 10 println rdd1 getNum
  • Java / Scala Future 由回调驱动

    简洁版本 我怎样才能创建一个Promise
  • Scala 集合不一致

    为什么 Scala Collections API 中的集合和列表之间缺乏一致性 例如 有不可变的 Set 但也有可变的 Set 如果我想使用后者 我可以简单地这样做 val set Set A set new A 但是 本身不存在可变列表
  • Scala:具有复杂结构的树插入尾递归

    我正在 scala 中创建自定义对象树 并且我的插入方法引发堆栈溢出 因为它不是尾递归 但是 我不太清楚如何使其尾递归 我见过使用 累加器 变量的相关示例 但它们要么是只能相乘和覆盖的整数之类的东西 要么是我在适应树时遇到困难的列表 这是我
  • Scala 中值类的隐式 Json 格式化程序

    我有许多值类组成了一个更大的对象案例类 final case class TopLevel foo Foo bar Bar final case class Foo foo String extends AnyVal final case
  • Scala 相当于 Java 的 Number

    我正在尝试为数值域类型构建类型层次结构 例如AYear is an Int 这是一个Number a Percentage is a Double 这是一个Number等等 我需要层次结构以便我可以调用toInt or toDouble关于
  • 使用原始类型模拟案例类

    考虑以下类型结构 trait HasId T def id T case class Entity id Long extends HasId Long 比方说 我们想在一些测试中模拟实体类 val entityMock mock Enti
  • 使用 Akka 玩 2.5 - 找不到参数超时的隐式值:akka.util.Timeout

    我正在尝试使用 Play 2 5 测试 Akka 但遇到了一个似乎无法解决的编译错误 我正在关注 Play 文档中的此页面 https playframework com documentation 2 5 x ScalaAkka http
  • Source.getLines 中的默认参数错误 (Scala 2.8.0 RC1)

    假设我运行 Scala 2 8 0 RC1 以下 scala 代码应该打印出文件 c hello txt 的内容 for line lt Source fromPath c hello txt getLines println line 但
  • 使用 Spark DataFrame 获取组后所有组的 TopN

    我有一个 Spark SQL DataFrame user1 item1 rating1 user1 item2 rating2 user1 item3 rating3 user2 item1 rating4 如何按用户分组然后返回TopN
  • Spark Scala 将列从一个数据帧复制到另一个数据帧

    我有一个原始数据框的修改版本 我在其上进行了聚类 现在我想将预测列恢复为原始 DF 索引没问题 因此匹配 我该怎么做 使用这段代码我得到一个错误 println Predicted dfWithOutput show println Ori
  • 缓存 Slick DBIO 操作

    我正在尝试加快 SELECT FROM WHERE name 的速度Play 中的查询类型 Scala 应用程序 我正在使用 Play 2 4 Scala 2 11 play slick 1 1 1 包 该软件包使用Slick 3 1版本
  • 类型级编程有哪些示例? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我不明白 类型级编程 是什么意思 也无法使用Google找到合适的解释 有人可以提供一个演示类型级编程的示例吗 范式的解释和 或定义将
  • 在文件复制/上传未完成时读取文件内容

    例如 每 5 秒 服务器检查文件是否已添加到特定目录 如果是 它会读取并处理它们 相关文件可能非常大 例如 100 Mo 因此将它们复制 上传到上述目录可能会很长 如果服务器尝试访问尚未完成复制 上传的文件怎么办 JAVA是如何管理这些并发
  • 为什么 GetThreadTimes 返回

    我试图测量线程中花费的时间以用于进度报告目的 但我从 GetThreadTimes 系统调用中得到非常奇怪的结果 给出以下程序 在 VS 2013 中编译 针对 NET 4 5 using System using System Diagn
  • 使用 scala 在 Flink 中进行实时流预测

    弗林克版本 1 2 0斯卡拉版本 2 11 8 我想使用 DataStream 来使用 scala 中的 flink 模型进行预测 我在使用 scala 的 flink 中有一个 DataStream String 其中包含来自 kafka

随机推荐