我正在编写一个小测试程序来尝试使用我在Scala项目中需要的Remote Actors。
基本目标是编写一个服务器的测试应用程序,该服务器可以处理一堆客户端和可以同时发送多个消息的更重要的客户端(如ping,请求更新和用户引发的数据请求)< / p>
我想出的是: 简要概述:客户端启动3个不同的actor,这些actor再次启动具有不同偏移的while循环中的actor,以便模拟相当随机的消息。
import scala.actors.remote.RemoteActor
import scala.actors.remote.Node
import scala.actors.Actor
trait Request
trait Response
case object WhoAmI extends Request
case class YouAre(s:String) extends Response
case object Ping extends Request
case object Pong extends Response
case class PrintThis(s:String) extends Request
case object PrintingDone extends Response
object Server {
def main(args: Array[String]) {
val server = new Server
server.start
}
}
class Server extends Actor {
RemoteActor.alive(12345)
RemoteActor.register('server, this)
var count:Int = 0
def act() {
while(true) {
receive {
case WhoAmI => {
count += 1
sender ! YouAre(count.toString)
}
case Ping => sender ! Pong
case PrintThis(s) => {
println(s)
sender ! PrintingDone
}
case x => println("Got a bad request: " + x)
}
}
}
}
object Act3 extends scala.actors.Actor {
def act = {
var i = 0
Thread.sleep(900)
while (i <= 12) {
i += 1
val a = new Printer
a.start
Thread.sleep(900)
}
}
}
class Printer extends scala.actors.Actor {
def act = {
val server = RemoteActor.select(Node("localhost",12345), 'server)
server ! PrintThis("gagagagagagagagagagagagaga")
receive {
case PrintingDone => println("yeah I printed")
case _ => println("got something bad from printing")
}
}
}
object Act2 extends scala.actors.Actor {
def act = {
var i = 0
while (i < 10) {
i+=1
val a = new Pinger
a.start
Thread.sleep(700)
}
}
}
class Pinger extends scala.actors.Actor {
def act = {
val server = RemoteActor.select(Node("localhost",12345), 'server)
server ! Ping
receive {
case Pong => println("so I pinged and it fits")
case x => println("something wrong with ping. Got " + x)
}
}
}
object Act extends scala.actors.Actor {
def act = {
var i = 0
while(i < 10) {
i+=1
val a = new SayHi
a.start()
Thread.sleep(200)
}
}
}
class SayHi extends scala.actors.Actor {
def act = {
val server = RemoteActor.select(Node("localhost",12345), 'server)
server ! "Hey!"
}
}
object Client {
def main(args: Array[String]) {
Act.start()
//Act2.start()
Act3.start()
}
}
问题在于事情并没有像我期望的那样顺利进行:
当我只启动一个客户演员时(通过评论其他人,就像我在Act2
中对Client
所做的那样)事情通常但并不总是顺利。如果我开始两个或更多演员,通常打印输出大量出现(意思是:没有任何事情一次发生,然后打印输出显得相当快)。客户端有时会终止,有时也不会终止。
这可能不是最大的问题,但它们足以让我感到非常不舒服。我在演员和远程演员上做了很多阅读,但我发现可用的信息相当缺乏。
尝试在适当的地方添加exit
个陈述。但这没有帮助。
有人知道我做错了什么吗?这里有任何一般技巧吗?一些dos和donts?
答案 0 :(得分:3)
我的猜测是你的问题源于使用receive
和Thread.sleep
阻止你的演员的线程。阻塞操作会占用actor的线程池中的线程,这可能会阻止其他actor执行,直到将新线程添加到池中。 This question可能会提供一些额外的见解。
您可以使用loop
,loopWhile
,react
和reactWithin
重写许多演员以使用非阻止操作。例如
import scala.actors.TIMEOUT
object Act extends scala.actors.Actor {
def act = {
var i = 0
loopWhile(i < 10) {
reactWithin(200) { case TIMEOUT =>
i+=1
val a = new SayHi
a.start()
}
}
}
}
当然,您可以通过编写自己的控件构造来消除一些样板:
def doWithin(msec: Long)(f: => Unit) = reactWithin(msec) { case TIMEOUT => f }
def repeat(times: Int)(f: => Unit) = {
var i = 0
loopWhile(i < times) {
f
i+=1
}
}
这将允许你写
repeat(10) {
doWithin(200) {
(new SayHi).start
}
}
答案 1 :(得分:1)
您可以尝试使用Akka actors framework http://akkasource.org/