Android 线程游戏中的演员/消息传递”;事件循环“;

Android 线程游戏中的演员/消息传递”;事件循环“;,android,multithreading,scala,actor,game-loop,Android,Multithreading,Scala,Actor,Game Loop,我正在构建一个Android应用程序(使用Scala 2.9)并使用一个线程渲染到SurfaceView;这是一个游戏,所以它应该经常更新。我认为这个问题类似于其他游戏“事件循环”,其中输入来自不同的线程 下面是当前依赖于同步的方法的大致近似值。它“工作得很好”,但我对必须使用显式同步和“捆绑”视图/输入线程有普遍的疑虑 视图,“UI线程”: 游戏,“游戏线程”: 我不希望显式使用同步,而是希望有如下内容: def View.onTouchEvent(e) { // on UI thread

我正在构建一个Android应用程序(使用Scala 2.9)并使用一个线程渲染到SurfaceView;这是一个游戏,所以它应该经常更新。我认为这个问题类似于其他游戏“事件循环”,其中输入来自不同的线程

下面是当前依赖于同步的方法的大致近似值。它“工作得很好”,但我对必须使用显式同步和“捆绑”视图/输入线程有普遍的疑虑

视图,“UI线程”:

游戏,“游戏线程”:

我不希望显式使用同步,而是希望有如下内容:

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
或类似工具手动实现这一点相对容易,但我真的不想在这里重新发明轮子。此外,使用这样一个参与者/队列来发回UI也很好——现在我正在使用Android的支持向UI线程发回(异步)可运行的消息

我简要介绍了几种不同的actor实现(主要是标准Scala和Scalaz)和一些不同的Java“消息传递”库,例如,但大多数似乎使用隐式线程或线程执行器服务。但是,在我的例子中,我希望在特定线程上的特定时间[运行actor并]处理消息。对于View.sendMessage,消息也应该在UI线程上处理,但计时并不重要,可以借助上面提到的可运行执行

那么,我想我的问题是,鉴于上述情况:

在这两个线程之间提供数据的“高效”和惯用方法是什么

(我也愿意接受这样的建议,即我完全无法理解Scala actors和/或Scalaz actors和/或其他消息传递库;Scalaz似乎可以按照我的设想工作,但我很难遵循。)

好吧,尽管我仍然想知道一种通用/可重用的方法来处理上述问题,实用性要求。这也可以通过在游戏线程上运行一个,然后将游戏“事件循环东西”放在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(..))
}
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(..))
}