我正在尝试在Android中编写游戏引擎,但我对线程并不太熟悉。
我的主题有一个属性mSurfaceHolder,它保存了我将要绘制的表面。我的线程的run()方法如下所示:
public void run() {
// We're running now
setState(STATE_RUNNING);
// Keep looping while the game is running or paused
while (mState == STATE_RUNNING || mState == STATE_PAUSED) {
synchronized (mSurfaceHolder) {
// If the game is running, update physics etc.
if (mState == STATE_RUNNING) {
updateGame();
}
// Draw the game even if it's paused
drawGame();
}
}
}
STATE_RUNNING
表示活动在前台并且游戏应该运行时的状态。
STATE_PAUSED
表示另一个活动进入前台时的状态。我不完全确定为什么我需要在它暂停时仍然绘制,但这就是我似乎从LunarLander example收集的内容。
我希望在观看活动时,游戏会更新并绘制(我使用LogCat进行测试)。然后,当我回到主屏幕或其他活动出现在顶部时,它将只是绘制。
当我正在观看活动时, 进行绘制和更新,因此游戏循环本身有效。但是当我离开活动时,它没有任何效果。这是从activity的onPause()调用的线程的pause()方法:
public void pause() {
Log.d("Game","Here");
synchronized (mSurfaceHolder) {
Log.d("Game","There");
// If the thread is running, pause it
if (mState == STATE_RUNNING) {
setState(STATE_PAUSED);
}
}
}
如您所见,为了测试此方法,我记录了一些消息。现在我离开活动时发现的是“Here”被记录,但“There”没有。由于我对线程知识有限(我几乎不知道synchronized
实际上做了什么),我相信这会发生,因为我的线程无法与表面持有者同步。但我不知道为什么它不同步。离开活动几秒钟后,我在LogCat中看到以下警告:
Activity pause timeout for HistoryRecord
知道为什么会这样吗?如果我尝试再次启动活动没有问题,线程会保持原样运行。
非常感谢。
编辑:刚刚发现其他内容。如果我在启动它的大约一秒钟内离开活动,该线程会暂停。然后,当同一任务仍在运行时,它将恢复并暂停,完全没有任何问题。我不知道为什么它会在短时间内发挥作用,但是如果我把它留下太久,它就不会。
编辑2 :好的......我修好了。但我不认为我应该做我做过的事情。我基本上从pause()和setState()方法(暂停()使用)中删除了与mSurfaceHolder
的任何同步。不,它应该按预期工作,但我认为同步是有原因的。
也许对我来说最好的问题是: 什么时候应该使用synchronized块同步线程与对象?在这种情况下,与SurfaceHolder同步的目的是什么?
答案 0 :(得分:3)
Java中的synchronize
关键字确保两个线程不能同时触及同一个对象,从而防止竞争条件。换句话说,它实现了锁定。
最有可能的是,你在这里遇到了僵局。另一个线程可能正在使用mSurfaceHolder
,因此持有此对象的锁。 synchronized (mSurfaceHolder)
中的代码将阻塞,直到其他线程完成,这显然没有发生。
但是,由于您实际上并没有以任何方式修改mSurfaceHolder
,因此没有理由对其进行锁定。您唯一需要记住的是,在调用时间pause()
和更新它的值之间可能会读取mState。如果这是一个问题,请在mState
上进行同步。