主演员的Scala / Akka NullPointerException

时间:2014-12-26 00:57:32

标签: java scala parallel-processing akka

我正在学习用于scala并行处理的akka​​框架,我正在尝试将java项目迁移到scala,这样我就可以同时学习akka和scala。当我在worker中进行一些计算后尝试从worker actor接收可变对象时,我在master actor上得到一个NullPointerException。所有代码都在......

之下
    import akka.actor._
    import java.math.BigInteger
    import akka.routing.ActorRefRoutee
    import akka.routing.Router
    import akka.routing.RoundRobinRoutingLogic

    object Main extends App {

      val system = ActorSystem("CalcSystem")
      val masterActor = system.actorOf(Props[Master], "master")
      masterActor.tell(new Calculate, ActorRef.noSender)
    }

    class Master extends Actor {

      private val messages: Int = 10;
      var resultList: Seq[String] = _

      //val workerRouter = this.context.actorOf(Props[Worker].withRouter(new RoundRobinRouter(2)), "worker")

      var router = {
        val routees = Vector.fill(5) {
          val r = context.actorOf(Props[Worker])
          context watch r
          ActorRefRoutee(r)
        }
        Router(RoundRobinRoutingLogic(), routees)
      }

      def receive() = {
        case msg: Calculate =>
          processMessages()
        case msg: Result =>
          resultList :+ msg.getFactorial().toString
          println(msg.getFactorial())

          if (resultList.length == messages) {
            end
          }
      }

      private def processMessages() {
        var i: Int = 0
        for (i <- 1 to messages) {
         // workerRouter.tell(new Work, self)
          router.route(new Work, self)
        }
      }

      private def end() {
        println("List = " + resultList)
        this.context.system.shutdown()
      }
    }


import akka.actor._
import java.math.BigInteger

class Worker extends Actor {

  private val calculator = new Calculator

  def receive() = {
    case msg: Work =>
      println("Called calculator.calculateFactorial: " + context.self.toString())
      val result = new Result(calculator.calculateFactorial)
      sender.tell(result, this.context.parent)

    case _ =>
      println("I don't know what to do with this...")

  }
}


import java.math.BigInteger

class Result(bigInt: BigInteger) {

  def getFactorial(): BigInteger = bigInt

}

import java.math.BigInteger

class Calculator {

  def calculateFactorial(): BigInteger = {

    var result: BigInteger = BigInteger.valueOf(1)
    var i = 0

    for(i <- 1 to 4) {      
      result = result.multiply(BigInteger.valueOf(i))      
    }        
    println("result: " + result)
    result
  }
}

2 个答案:

答案 0 :(得分:0)

您使用resultList初始化null,然后尝试附加内容。

答案 1 :(得分:0)

你的计算是否会停止?在行

resultList :+ msg.getFactorial().toString

您正在创建附加了元素的序列副本。但是没有var resultList

的作业

此行可以根据需要使用。

resultList = resultList :+ msg.getFactorial().toString

我建议你避免在actor中使用可变变量并使用context.become https://github.com/alexandru/scala-best-practices/blob/master/sections/5-actors.md#52-should-mutate-state-in-actors-only-with-contextbecome