我遇到了下面的代码,我想知道它是否完全符合我的想法:
synchronized(sObject) {
mShouldExit = true;
sObject.notifyAll()
while (!mExited) {
try {
sObject.wait();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
关于上下文:有另一个线程检查mShouldExit
(在sObject
监视器内)并在这种情况下退出。
这对我来说似乎不是正确的模式。如果发生中断,它会再次设置中断状态,所以当它返回时sObject.wait()
,另一个InterruptedException 会来等等等等。因此,它永远不会进入真正的等待状态(sObject.wait()
),即永远不会释放sObject
监视器。这可能会导致无限循环,因为其他线程无法将 mExiting 设置为 true,因为它永远无法进入 sObject 的监视器。(所以我认为interrupt()
调用是一个错误,它不能在这里使用。)我错过了什么吗?
请注意,代码片段是官方 Android 框架源代码的一部分。
更新:实际上,情况更糟,因为当您的 GL 渲染开始时,Android 中使用了相同的模式。官方源代码GLSurfaceView.GLThread.surfaceCreated()
:
public void surfaceCreated() {
synchronized(sGLThreadManager) {
if (LOG_THREADS) {
Log.i("GLThread", "surfaceCreated tid=" + getId());
}
mHasSurface = true;
sGLThreadManager.notifyAll();
while((mWaitingForSurface) && (!mExited)) {
try {
sGLThreadManager.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
您可以以类似的方式重现该错误:确保您的 UI 线程具有其中断状态标志,然后添加您的 GLSurfaceView 并开始 GL 渲染(通过setRenderer(...)
,但在某些设备上,确保您的 GLSurfaceView 具有Visibility.VISIBLE
状态,否则渲染将不会开始)。
如果您按照上述步骤操作,您的 UI 线程将陷入无限循环,因为上面引用的代码将不断生成InterruptedException
(due to wait()
),因此 GL 线程将永远无法设置mWaitingForSurface
为 false。
根据我的测试,似乎这样的无限循环也会导致无休止的 GC_CONCURRENT 垃圾收集序列(或者,至少是 logcat 中的此类消息)。有趣的是,之前有人在 stackoverflow 上遇到了一个未知的定义不明确的问题,这可能与此有关: How to solve GC_concurrent freed?
难道他的 UI 线程可能将其中断标志设置为 true,并且他正在使用 GLSurfaceView 作为他提到的地图吗?只是一个假设,一个可能的场景。