Java 线程等待

Java 线程等待,java,android,multithreading,Java,Android,Multithreading,我的Java对以下问题的理解有问题。我在Google Store上有一个游戏,偶尔在我的开发者控制台上会出现一个错误,指向我自定义活动中的onPause方法。我很难再现这个问题,也很难理解线程的内在机制。此特定ANR的堆栈调用如下所示(proguared): 编辑: 看起来像是阻塞UI线程(Activity.onPause)-间歇性的性质可能与锁定的其他竞争者有关。我真的不知道问题出在哪里,线程不是我的强项。ANR最有可能发生是因为您在主线程上阻塞(onPause在主线程上)使用wait-但是w

我的Java对以下问题的理解有问题。我在Google Store上有一个游戏,偶尔在我的开发者控制台上会出现一个错误,指向我自定义活动中的onPause方法。我很难再现这个问题,也很难理解线程的内在机制。此特定ANR的堆栈调用如下所示(proguared):

编辑:


看起来像是阻塞UI线程(Activity.onPause)-间歇性的性质可能与锁定的其他竞争者有关。我真的不知道问题出在哪里,线程不是我的强项。ANR最有可能发生是因为您在主线程上阻塞(
onPause
在主线程上)使用
wait
-但是
wait
可能是即时的-它可能不是-这完全取决于此处未显示的“其他”代码,该代码
notify
用于threadsLock对象。我在代码中看到了在threadsLock上使用notifyAll的两种用法。一个是从View派生的类的wihin onDrawFrame,另一个也是在同一类的onDrawFrame中。在onDrawFrame中实现了某种状态类型的机器。我将在编辑后的原始问题中分享它。如果你的应用程序在5秒内没有响应输入事件,将抛出ANR!在上面的上下文中,输入事件最有可能是用户导致另一个应用程序进入前台-导致您的应用程序进入
onPause
。有一种
wait(timeout)
方法,允许您捕获这些情况并处理-使用1s,例如和“break”-但如果gl线程被锁定,则可以将问题转移到
onResume
。注意:已获得同步锁,因此发布的代码不相关-只有发出“notify*”的代码相关。。。
  at java.lang.Object.wait (Object.java)
- waiting on <0x0f6bfc18> (a java.lang.Object)
  at java.lang.Object.wait (Object.java:442)
  at java.lang.Object.wait (Object.java:568)
  at xengine.XEngineActivity.onPause (XEngineActivity.java)
- locked <0x0f6bfc18> (a java.lang.Object)
  at android.app.Activity.performPause (Activity.java:8168)
  at android.app.Instrumentation.callActivityOnPause (Instrumentation.java:1508)
  at android.app.ActivityThread.performPauseActivityIfNeeded (ActivityThread.java:4725)
@Override
protected void onPause() {
    synchronized(threadsLock) {
        if(gameState != GameState.INITIALIZATION) {
            gameState = isFinishing() ? GameState.FINISHED : GameState.PAUSED;
            while(true) {
                try {
                    threadsLock.wait();
                    break;
                } catch (InterruptedException e) {
                    // TODO: ??
                }
            }
        }
    }
    audioMgr.pauseMusic();
    audioMgr.pause(true);
    inputMgr.onPause(); 
    if(isFinishing())
        audioMgr.release(); 
    else
        audioMgr.pauseMusic();
    glView.onPause();
    super.onPause();
}
public void onDrawFrame(GL10 unused) {
    GameState gameState;
    boolean backButton;

    synchronized(xengine.threadsLock) {
        gameState = xengine.gameState;
        backButton = xengine.backButtonPressed;
    }

    if(backButton) {
        xengine.getScreen().onBackButtonPressed();
    }

    if(gameState == GameState.INITIALIZATION) {
        xengine.getScreen().onResume();
        synchronized(xengine.threadsLock) {
            xengine.gameState = GameState.RUNNING;
        }
        previousFrameTime = SystemClock.uptimeMillis();
    }
    else if(gameState == GameState.RUNNING) {
        gameRunning();
    } 
    else if(gameState == GameState.PAUSED) {
        gamePaused();
    } 
    else if(gameState == GameState.FINISHED) {
        gameFinished();         
    }

    if(backButton) {
        synchronized(xengine.threadsLock) {
            xengine.backButtonPressed = false;
        }
    }
}

private void gamePaused() {
    xengine.getScreen().onPause();
    xengine.shadersMgr.release();
    synchronized(xengine.threadsLock) {
        xengine.gameState = GameState.IDLE;
        xengine.threadsLock.notifyAll();
    }
}