android - 线程游戏 “event loop”中的Actor/消息传递

标签 android multithreading scala actor game-loop

我正在构建一个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/

相关文章:

android - 如何使用 scrypt 生成 256 位 key ?

java - 自定义 ListView 在 Fragment 中旋转时消失

java - 尝试在 fragment 选项卡中添加 map 时出错

c# - 同步问题

scala - 如何让 "sbt hello, world"运行?

android - 关键捕获问题

multithreading - 如何使用 g++ 在 64 位 Solaris sparc 上编译线程本地存储 (TLS)

java - Java 1.4 中 Lock.tryLock() 的替代方案

java - 如何将 Java 双冒号运算符 (::) 翻译成 Scala?

scala - 如何在 SBT 版本中跳过测试?