Ma simulation utilise des acteurs et Scala 2.8-Snapshot. En Java JRE 1.5 ça marche bien - les 40 gears (acteurs) travaillent simultanément. En utilisant Java JRE 1.6 seulement 3 vitesses travaillent simultanément. Je l'ai testé avec et sans interface graphique: les deux donnent le même résultat.Scala Acteurs: comportement différent sur JRE 1.5 et 1.6
Ma simulation avec une interface graphique est disponible sur github: http://github.com/pmeiclx/scala_gear_simulation
Peut-être que vous vous souvenez de my first problem with actors. Après avoir résolu ces problèmes, j'ai fait une interface graphique pour la simulation et j'ai obtenu ce nouveau comportement "étrange".
Voici le code sans interface graphique:
package ch.clx.actorversions
import actors.Actor
import actors.Actor._
import collection.mutable.ListBuffer
case class ReceivedSpeed(gear: Gear)
case object StartSync
case class SyncGear(controller: GearController, syncSpeed: Int)
object ActorVersion {
def main(args:Array[String]) = {
println("[App] start with creating gears")
val gearList = new ListBuffer[Gear]()
for (i <- 0 until 100) {
gearList += new Gear(i)
}
val gearController = new GearController(gearList)
gearController.start()
gearController ! StartSync
}
}
/**
* CONTROLLER
*/
class GearController(nGears: ListBuffer[Gear]) extends Actor {
private var syncGears = new ListBuffer[Gear]
private var syncSpeed = 0
def act = {
while(true) {
receive {
case StartSync => {
println("[Controller] Send commands for syncing to gears!")
var speeds = new ListBuffer[Int]
nGears.foreach(e => speeds += e.speed)
//Calc avg
//var avgSpeed = speeds.foldLeft(0)(_ + _)/speeds.length
//var avgSpeed = speeds.foldLeft(0) { (x, y) => x + y }/speeds.length
syncSpeed = (0/:speeds)(_ + _)/speeds.length //Average over all gear speeds
//TODO syncSpeed auf Median ausrichten
println("[Controller] calculated syncSpeed: "+syncSpeed)
nGears.foreach{e =>
e.start()
e ! SyncGear(this, syncSpeed)
}
println("[Controller] started all gears")
}
case ReceivedSpeed(gear: Gear) => {
println("[Controller] Syncspeed received by a gear ("+gear.gearId+")")
//println("[Controller] mailboxsize: "+self.mailboxSize)
syncGears += gear
if(syncGears.length == nGears.length) {
println("[Controller] all gears are back in town!")
System.exit(0)
}
}
case _ => println("[Controller] No match :(")
}
}
}
}
/**
* GEAR
*/
class Gear(id: Int) extends Actor {
private var mySpeed = scala.util.Random.nextInt(1000)
private var myController: GearController = null
def speed = mySpeed
def gearId = id
/* Constructor */
println("[Gear ("+id+")] created with speed: "+mySpeed)
def act = {
loop {
react {
case SyncGear(controller: GearController, syncSpeed: Int) => {
//println("[Gear ("+id+")] activated, try to follow controller command (form mySpeed ("+mySpeed+") to syncspeed ("+syncSpeed+")")
myController = controller
adjustSpeedTo(syncSpeed)
}
}
}
}
def adjustSpeedTo(targetSpeed: Int) = {
if(targetSpeed > mySpeed) {
mySpeed += 1
self ! SyncGear(myController, targetSpeed)
}else if(targetSpeed < mySpeed) {
mySpeed -= 1
self ! SyncGear(myController, targetSpeed)
} else if(targetSpeed == mySpeed) {
callController
}
}
def callController = {
println("[Gear ("+id+")] has syncSpeed")
myController ! ReceivedSpeed(this)
}
}
FYI: J'ai expliqué ce problème à Philipp Haller et il l'a corrigé dans le coffre. Donc, lorsque 2.8 est libéré, il ne devrait pas avoir le problème. https://lampsvn.epfl.ch/trac/scala/changeset/20950/scala/trunk/src/actors –
Désolé, j'étais un peu occupé. Avec le nouvel instantané, cela fonctionne. Pas parfait mais ça marche. Je vous remercie! – meip