java.lang.IllegalMonitorStateException等待Future

时间:2018-01-23 18:08:33

标签: scala akka akka-stream

我需要等SourceQueueWithComplete.offer才能完成:

  val config = ConfigFactory.defaultApplication()
  implicit val system: ActorSystem = ActorSystem("TestSystem", config)
  implicit val mat: ActorMaterializer = ActorMaterializer()
  implicit val ctx = system.dispatcher

  val queue =
    Source.queue(5, OverflowStrategy.backpressure)
      .async
      .mapAsync(8) { x: Int =>
        Future {
          println(s"Processed $x")
          x
        }
      }
      .to(Sink.ignore)
      .run()

  for (i <- 1 to 10) {
    println(s"Queueing $i...")
    for (_ <- queue.offer(i))
      println(s"$i has been queued!")
  }

输出:

Queueing 1...
Exception in thread "main" java.lang.IllegalMonitorStateException
Queueing 2...
    at java.lang.Object.wait(Native Method)
Queueing 3...
    at java.lang.Object.wait(Object.java:502)
Queueing 4...
    at Node1$.delayedEndpoint$Node1$1(Node1.scala:95)
Queueing 5...
    at Node1$delayedInit$body.apply(Node1.scala:12)
Queueing 6...
    at scala.Function0.apply$mcV$sp(Function0.scala:34)
Queueing 7...
Queueing 8...
    at scala.Function0.apply$mcV$sp$(Function0.scala:34)
Queueing 9...
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
Queueing 10...
    at scala.App.$anonfun$main$1$adapted(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:389)
    at scala.App.main(App.scala:76)
    at scala.App.main$(App.scala:74)
    at Node1$.main(Node1.scala:12)
    at Node1.main(Node1.scala)
1 has been queued!
2 has been queued!
4 has been queued!
5 has been queued!
3 has been queued!
6 has been queued!
Processed 1
Processed 2
Processed 3
Processed 4
Processed 5
Processed 6

queue.offer封闭在synchronized块中无济于事。

1 个答案:

答案 0 :(得分:1)

这些错误提示了与DelayedInit相关的内容,自Scala 2.11.0以来不推荐使用(来自Scaladoc:“DelayedInit语义可能令人惊讶。”)。大概你正在使用扩展DelayedInit的{​​{3}},但如果没有看到更多代码,就很难诊断出这可能是一个问题。

此外,您可以使用另一个Source向队列提供元素。以下作品:

import akka.stream._
import akka.stream.scaladsl._
import akka.actor.ActorSystem
import scala.concurrent._

object Main extends App {
  implicit val system = ActorSystem("TestApp")
  implicit val materializer = ActorMaterializer()
  implicit val ec = system.dispatcher

  val queue =
    Source.queue(5, OverflowStrategy.backpressure)
          .async
          .mapAsync(8) { x: Int => Future(x) }
          .to(Sink.foreach(y => println(s"Processed: $y")))
          .run()

  Source(1 to 10)  
    .mapAsync(1) { x =>
      println(s"Offering: $x")
      queue.offer(x)
    }
    .runWith(Sink.ignore)
}