multithreading - Scala 的阻塞上下文似乎不适用于混合阻塞/非阻塞作业。为什么?

标签 multithreading scala concurrency fork-join

我试图理解 blocking构造。虽然它内部是如何工作的并不完全清楚,但我得到的一般想法是,只要我使用 Scala 的全局线程池,用 blocking 包装我的代码。上下文将确保线程池为该作业创建额外的空间(因为它不受 CPU 限制)。

  (1 to 1000).foreach { i =>
    Future {
      println(i)
      Thread.sleep(100 * 1000)
    }
  }

将很快表明只有 8 个作业可以同时运行,而
  (1 to 1000).foreach { i =>
    Future {
        blocking {
            println(i)
            Thread.sleep(100 * 1000)
        }
    }
  }

将显示现在我们有大约 250 个同时工作。哇!
然后让我措手不及的是
  (1 to 1000).foreach { i =>
    Future {
      println(i)
      Thread.sleep(100 * 1000)
    }
  }

  ('a' to 'z').foreach { c =>
    Future {
        blocking {
            println(c)
            Thread.sleep(100 * 1000)
        }
    }
  }

将再次只显示 8 个并发作业——阻塞作业不会立即执行。

为什么是这样? blocking的内部机制到底是什么?语境?

最佳答案

blocking只有在您进入阻塞上下文后才会生效。由于您有 8 个非阻塞 future 在运行,因此不会启动任何新 future ,因此它们无法进入阻塞上下文。换句话说,Scala 不会“知道”它们在开始执行之前正在阻塞。

您可以将第二个代码段视为如下工作:

  • 第一个 future 已创建并开始。
  • 第一个 future 通过调用 blocking 表示它正在阻塞,因此实现为更多 future 腾出了空间。
  • 同时,在主线程上,创建并启动了第二个 future 。
  • ...

  • 而你的最后一个片段是这样工作的:
  • 第一个 future 已创建并开始。它并不表示它正在阻塞。
  • 第二个 future 也是如此。
  • ...
  • 第 9 个 future 已创建,但尚未启动,因为有 8 个非阻塞 future 。
  • ...
  • 第 1001 个 future (第二个循环中的第一个)已创建,但未启动,因为有 8 个非阻塞 future 。由于它没有启动,它永远没有机会通过调用 blocking 来告诉实现它正在阻塞。 .
  • 关于multithreading - Scala 的阻塞上下文似乎不适用于混合阻塞/非阻塞作业。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55365841/

    相关文章:

    c++ - 绘制线程上下文切换的工具

    java - 如何停止下一个线程在 ScheduledThreadPoolExecutor 中运行

    list - 在 Scala 中,如何将默认值传递给 List.find?

    java - 为什么当队列溢出且所有线程都忙时拒绝处理程序不调用

    linux - 您可以在 Go 中运行程序的独立实例吗?

    android - CountDownTimer 更新和阻塞

    java - JMM 中的执行和因果关系要求

    scala - 是否可以将 Spring MVC 与 Groovy 或 Scala 一起使用?

    scala - 需要什么方法来创建自定义 Applicative Functor 以与 scalaz 一起使用 |@|

    java - 在 Java 6 中用于并发访问列表的最佳方法