2

我正在尝试在 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表示 Activity 处于前台并且游戏应该正在运行时的状态。 STATE_PAUSED表示另一个活动进入前台时的状态。我不完全确定为什么在暂停时仍需要绘制,但这似乎是我从LunarLander 示例中收集到的。

我希望在我查看活动时,游戏会更新和绘制(我使用 LogCat 进行测试)。然后当我返回主屏幕或顶部出现另一个活动时,它只会绘制。

好吧,它确实在我观看活动时绘制和更新,因此游戏循环本身可以工作。但是当我离开活动时,它没有任何效果。这是从活动的 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);
        }
    }
}

如您所见,为了测试此方法,我记录了一些消息。现在,当我离开活动时,我发现“这里”已记录,但“那里”没有。现在,由于我对线程的了解有限(我几乎不知道synchronized实际上是做什么的),我相信这会发生,因为我的线程无法与表面保持器同步。但我不知道为什么它不同步。离开活动几秒钟后,我在 LogCat 中看到以下警告:

Activity pause timeout for HistoryRecord

知道为什么会发生这种情况吗?如果我再次尝试启动 Activity 没有问题,线程会保持原样运行。

非常感谢。

编辑:刚刚发现了别的东西。如果我在启动活动后大约一秒钟内离开活动,线程就会暂停。然后它将在同一任务仍在运行时再次恢复并暂停,完全没有问题。我不知道为什么在短时间内它会起作用,但如果我离开它太久,它就不会了。

编辑2:好的......我修好了。但我不认为我应该做我做过的事。我基本上已经mSurfaceHolder从 pause() 和 setState() 方法(由 pause() 使用)中删除了任何同步。不,它按预期工作,但我认为同步是有原因的。

也许对我来说最好的问题是:何时应该使用同步块将线程与对象同步?而在这种情况下,与 SurfaceHolder 同步的目的是什么?

4

1 回答 1

3

Java 中的synchronize关键字确保两个线程不能同时接触同一个对象,从而防止竞争条件。换句话说,它实现了锁定。

很可能,您在这里遇到了死锁。另一个线程可能正在使用mSurfaceHolder,因此持有该对象的锁。您的代码synchronized (mSurfaceHolder)将阻塞,直到另一个线程完成,这显然没有发生。

但是,由于您实际上并未mSurfaceHolder以任何方式进行修改,因此没有理由对其进行锁定。您唯一需要记住的是 mState 可能会在pause()被调用的时间和您更新它的值之间被读取。如果这是一个问题,那么在mState.

于 2010-06-30T22:19:27.797 回答