我正在构建一个Android应用程序(使用Scala 2.9),并且正在使用一个渲染到SurfaceView的线程。这是针对游戏的,因此应尽可能频繁地进行更新。我想这个问题类似于其他游戏“事件循环”,其中输入来自不同的线程。
这是依赖于同步的当前方法的大致近似。它“足够好用”,但是我不得不担心必须使用显式同步并“占用” View /输入线程。
查看“UI线程”:
def View.onTouchEvent(e) { // on UI thread
Game.handleInput(e)
}
游戏,“游戏线程”:
def Game.handleInput(e) = S synchronized { // on UI thread
alterStateBasedOnInput
}
def Game.run () { // on Game thread
while (running) {
S synchronized {
doGameStuff
}
View.post(someStateRelayedViaRunnable)
yield
}
}
与其明确地使用同步,我想拥有这样的东西:
def View.onTouchEvent(e) { // on UI thread
Game.sendMessage(e)
}
def Game.run () { // on Game thread
while (running) {
processMessage
doGameStuff
View.sendMessage(someState) // hopefully same as Game.sendMessage
yield
}
}
现在,使用
ConcurrentLinkedQueue
或类似的代码手动实现相对容易,但是我真的不想在这里重新发明轮子。此外,也可以使用这样的actor/队列将其回发到UI上很好-现在,我正在使用Android的支持将(异步)Runnable发布到UI线程。我简要介绍了几种不同的actor实现(主要是标准的Scala和Scalaz)以及一些不同的Java“消息传递”库,例如Jetlang,但是大多数似乎使用隐式线程或线程执行器服务。但是,就我而言,我希望在特定时间在特定线程上[运行参与者并]处理消息。对于View.sendMessage,消息也应该在UI线程上进行处理,但是时间安排并不那么重要,并且可以背负上述Runnable执行。
然后,鉴于上述原因,我想我的问题是:
在这两个线程之间馈送数据的好方法(如“高效”的和惯用的方法)是什么?
(我也很乐意接受这样的建议,即我完全不了解Scala Actor 和/或Scalaz Actor 和/或其他消息传递库; Scalaz似乎可以按照我的设想工作,但是我很难遵循)
最佳答案
好吧,尽管我仍然想知道上述方法的通用/可重用方法,但实用性要求很高。也可以通过在游戏线程上运行Looper,然后将游戏“事件循环内容”放入IdleHandler内来完成此操作,但是我不喜欢这种反转。
这是我目前的实现方式:
游戏/线程类:
var handler: Handler = _ // handler created on View thread
// Send Message to Looper that exists on View thread
// (Created implicitly for all UI threads.)
def publishEvent(event: OutputEvent) {
handler.obtainMessage(0, event).sendToTarget
}
protected val queue = new ConcurrentLinkedQueue[InputEvent]
def queueEvent(event: InputEvent) { // on UI thread
queue.add(event)
}
def processQueuedEvents() { // on game Thread
@tailrec
def processNextEvent {
val event = queue.poll
if (event ne null) {
doStuffWithInputEvent(event)
processNextEvent
}
}
processNextEvent
}
override def run() { // on game Thread
while (running) {
processQueuedEvents
doOtherGameStuff ~ call_publishEvent ~ etc
}
}
查看类别:
// Created on UI thread, passed to Game instance
// (The Looper will dispatch Messages to Handlers.)
val handler = new Handler {
override def handleMessage(m: Message) {
val event = m.obj
doStuffWithOutputEvent(event)
}
}
// on UI thread
override def onTouch(v: View, ev: MotionEvent): Boolean = {
// safely queued, will be processed at the start of each game loop
game.queueEvent(InputEvent(..))
}
关于android - 线程游戏 “event loop”中的Actor/消息传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14372108/