

c:\temp>g8 typesafehub/akka-scala-sbt
Akka 2.0 Project Using Scala and sbt
organization [org.example]: akka.tutorial
package [org.example]: akka.tutorial.first.scala
name [Akka Project In Scala]: PI Calculator
akka_version [2.0]:
version [0.1-SNAPSHOT]:
Applied typesafehub/akka-scala-sbt.g8 in pi-calculator
c:\temp>cd pi-calculator
./src/main/scala/akka/tutorial/first/scala/ file in the appropriate folder ( ./src/main/scala/akka/tutorial/first/scala/ ) and import the necessary libraries:import akka.actor._
import akka.routing.RoundRobinRouter
import akka.util.Duration
import akka.util.duration._
Master actor that creates a multitude of Worker actors and initializes the calculation. To do this, he divides the entire task into small operations and sends these operations for the Worker to perform to the actors. After performing the operations, the Worker actors return the results for the aggregation. After the calculation is completed, the Master actor sends the result Listener actor, which displays it on the screen.Calculate - sent to the Master actor to start the calculationWork - sent by Master actor Worker actors, contains descriptions of the operation to be performedResult - sent by Worker actors Master actorPiApproximation - sent by Master Listener actor to actor, contains the result of the calculation and the time spent on the calculationsealed trait PiMessage case object Calculate extends PiMessage case class Work (start: Int, nrOfElements: Int) extends PiMessage case class Result (value: Double) extends PiMessage case class PiApproximation (pi: Double, duration: Duration)
Worker ActorWorker actor. This is done by mixing the Actor trait and defining the receive method. This method is a handler for incoming messages: class Worker extends Actor {
   // calculatePiFor ...
   def receive = {
     case Work (start, nrOfElements) ⇒
       sender!  Result (calculatePiFor (start, nrOfElements)) // perform the work
   }
 }
Work message handler, which creates a Result response message after the calculatePiFor operation and sends it back to the sender. Now let's implement calculatePiFor : def calculatePiFor (start: Int, nrOfElements: Int): Double = {
   var acc = 0.0
   for (i ← start until (start + nrOfElements))
     acc + = 4.0 * (1 - (i% 2) * 2) / (2 * i + 1)
   acc
 }
Master ActorMaster actor is a bit more complicated. a cyclic router is created in its constructor to facilitate the distribution of operations between Worker actors:val workerRouter = context.actorOf ( Props [Worker] .withRouter (RoundRobinRouter (nrOfWorkers)), name = "workerRouter")
Master Actor. This actor is created with the following parameters:Worker actorsWorker actor class Master (nrOfWorkers: Int, 
   nrOfMessages: Int, 
   nrOfElements: Int, 
   listener: ActorRef) extends Actor {
   var pi: Double = _
   var nrOfResults: Int = _
   val start: Long = System.currentTimeMillis
   val workerRouter = context.actorOf (
     Props [Worker] .withRouter (RoundRobinRouter (nrOfWorkers)), name = "workerRouter")
   def receive = {
     // handle messages ...
   }
 }
ActorRef object, which is a reference to the Listener actor, is passed to the Master actor. It should be noted that the transfer of messages between actors is always done through such links. def receive = {
   case Calculate ⇒
     for (i ← 0 until nrOfMessages) 
       workerRouter!  Work (i * nrOfElements, nrOfElements)
   case Result (value) ⇒
     pi + = value
     nrOfResults + = 1
     if (nrOfResults == nrOfMessages) {
       // Send the result to the listener
       listener!  PiApproximation (pi, duration = (System.currentTimeMillis - start) .millis)
       // Stops this actor and children
       context.stop (self)
     }
 }
Master actor stops using the context.stop(self) command.Listener ActorPiApproximation message from the Master actor, prints the result and stops the actor system: class Listener extends Actor {
   def receive = {
     case PiApproximation (pi, duration) ⇒
       println ("\ n \ tPi approximation: \ t \ t% s \ n \ tCalculation time: \ t% s"
         .format (pi, duration))
       context.system.shutdown ()
   }
 }
 object Pi extends App {
   calculate (nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000)
   // actors and messages ...
   def calculate (nrOfWorkers: Int, nrOfElements: Int, nrOfMessages: Int) {
     // Create an Akka system
     val system = ActorSystem ("PiSystem")
     // create the result listener 
     // shutdown the system
     val listener = system.actorOf (Props [Listener], name = "listener")
     // create the master
     val master = system.actorOf (Props (new Master (
       nrOfWorkers, nrOfMessages, nrOfElements, listener)),
       name = "master")
     // start the calculation
     master!  Calculate
   }
 }
sbt . Then we execute the following sequence of commands:c:\temp\pi-calculator>sbt
[info] Loading project definition from C:\temp\pi-calculator\project
[info] Set current project to PI Calculator (in build file:/C:/temp/pi-calculator/)
> compile
[success] Total time: 0 s, completed 20.03.2012 16:33:03
> run
[info] Running akka.tutorial.first.scala.Pi
Pi approximation: 3.1415926435897883
Calculation time: 423 milliseconds
[success] Total time: 1 s, completed 20.03.2012 16:33:25
> run
[info] Running akka.tutorial.first.scala.Pi
Pi approximation: 3.1415926435897883
Calculation time: 1160 milliseconds
[success] Total time: 2 s, completed 20.03.2012 16:35:16
> run
[info] Running akka.tutorial.first.scala.Pi
Pi approximation: 3.1415926435897905
Calculation time: 388 milliseconds
[success] Total time: 1 s, completed 20.03.2012 16:36:55
> run
[info] Running akka.tutorial.first.scala.Pi
Pi approximation: 3.141592643589789
Calculation time: 372 milliseconds
[success] Total time: 1 s, completed 20.03.2012 16:40:04
Source: https://habr.com/ru/post/140368/
All Articles