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