【问题标题】:The concurrent.blocking in future not work as expected in some scenario在某些情况下,未来的 concurrent.blocking 无法按预期工作
【发布时间】:2018-02-25 06:32:05
【问题描述】:

帮助解释 Scala 未来的 2 个现象(代码 4 和代码 5 中的粗体),谢谢。

代码1

package com.tst
import akka.actor.{Actor, ActorSystem, Props}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

class MyActor extends Actor {
  def receive = {
    case _ =>
      for (i <- 1 to 6) {
        Future {
          println("start")
          Thread.sleep(30000)
          println("end")
        }
      }
  }
}

object Test extends App {
  val system = ActorSystem()
  val myActor = system.actorOf(Props[MyActor])
  myActor ! 'msg
}

对于code1,由于我的cpu core是4,所以前30秒,我们只能看到4start打印,对我来说没问题。 (如果您的 cpu 有更多核心,例如 8 核心,您可以将循环从 6 更改为 10 以重现我的问题)

代码2

package com.tst
import akka.actor.{Actor, ActorSystem, Props}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future, blocking}

class MyActor extends Actor {
  def receive = {
    case _ =>
      for (i <- 1 to 6) {
        Future {
          blocking {
            println("start")
            Thread.sleep(30000)
            println("end")
          }
        }
      }
  }
}

object Test extends App {
  val system = ActorSystem()
  val myActor = system.actorOf(Props[MyActor])
  myActor ! 'msg
}

对于code2,由于添加了blocking,因此使用了额外的线程,所以我们首先可以看到6个start打印,对我来说没有问题。

代码3

package com.tst
import akka.actor.{Actor, ActorSystem, Props}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future, blocking}

class MyActor extends Actor {
  def receive = {
    case _ =>
      for (i <- 1 to 6) {
        Future {
          blocking { // lineA
            println("startpre")
            Thread.sleep(30000)
            println("endpre")
          }
        }
      }

      Thread.sleep(2000)

      for (i <- 1 to 6) {
        println("+")
        Future {
          blocking { // lineB
            println("start")
            Thread.sleep(30000)
            println("end")
          }
        }
      }
  }
}

object Test extends App {
  val system = ActorSystem()
  val myActor = system.actorOf(Props[MyActor])
  myActor ! 'msg
}

对于 code3,我们可以看到 6 startpre & 6 start 在前 30 秒打印,对我来说没问题。

code4

只需删除code3中的lineA,输出为:

startpre
startpre
startpre
startpre
+
+
+
+
+
+

这是我的第一个问题:为什么我在前 30 秒只能看到 4 个startpre?为什么 lineB 中的 blocking 在这里不起作用?以我的理解,我也应该看到6个start

code5

只删除code3的lineB,如果code4中删除lineA记得取消删除,输出为:

startpre
startpre
startpre
startpre
startpre
startpre
+
+
+
+
+
+
start

这是我的第二个问题:这里有 1 个start 可见,但所有 4 个线程都已被占用,并且为 lineA 的 Future 启动了 2 个额外线程,为什么仍然为 lineB 留下一个线程打印 1 start?

【问题讨论】:

    标签: scala akka future


    【解决方案1】:

    Here 在我看来它描述得很好。

    将部分代码放在blocking 中通知执行上下文可能需要一些其他线程结果来完成此阻塞。因此运行另一个线程来完成加速评估是合理的。

    换句话说,在您的情况下,code4 4 个线程正忙于从第一个循环执行 Futures,它们未标记为 blocking,因此没有理由在池中添加另一个工作线程,因此,没有线程从第二个循环执行任何新的Future

    code5 中,所有线程都忙于Future,标记为blocking。另一个线程已启动,被另一个循环中的Future 占用,而没有blocking,因此没有理由再添加一个线程。

    【讨论】:

      猜你喜欢
      • 2021-06-15
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-25
      • 1970-01-01
      • 1970-01-01
      • 2021-05-28
      相关资源
      最近更新 更多