我遇到下面的代碼的退出信號(在Android的錯誤?),我想知道,如果它不正是我想象的那樣:處理InterruptedException的等待
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
(由於wait()
),因此GL線程將永遠無法設定mWaitingForSurface
假。
根據我的測試,似乎這樣無限循環也將導致GC_CONCURRENT垃圾收集(或者,至少,在logcat中這樣的消息)的循環順序。有趣的是,有人對早期計算器一個未知的沒有準確定義的問題,這可能與: How to solve GC_concurrent freed?
難道就沒有可能,也許他的UI線程有其中斷標誌設置爲true,和他使用的一個GLSurfaceView他提到的地圖?只是一個假設,一個可能的場景。
可能的重複[處理Java中的InterruptedException](http://stackoverflow.com/questions/3976344/handling-interruptedexception-in-java)和這一個:http://stackoverflow.com/questions/5915156/如何可以殺死線程無使用停止/ 5915306#5915306 – assylias
它與鏈接的第一個主題無關(除了事實都與InterruptedException有關)。這是一個更復雜的問題,其他問題也完全是這樣。 (我知道你寫了「可能」,所以我只是告訴大家,它肯定不是)。編輯評論後添加的第二個更相關,它確切地證實了我懷疑上面的代碼是錯誤的,但既然它是官方的Android源代碼,那麼專家的明確回答將會很好。 –
你是對的 - 事實上,這不是重複的事實,重置被中斷的狀態將立即等待退出。有人可能會看到這樣做的好理由... – assylias