2010-06-30 149 views
9

的時候,這裏是我的情況: 我建立一個遊戲,Android和我的遊戲的活動是由它可以對遊戲邏輯和渲染線程的自定義surfaceView的。該架構類似於Google網站上的LunarLander演示。「主題已經開始」恢復活動

當活動啓動時,它會創建surfaceView並調用這個方法:

@Override 
    public void surfaceCreated(SurfaceHolder holder) 
    { 
     renderThread.start(); 
    } 

當我按下home鍵退出遊戲時,在onPause()方法被調用,調用surfaceDestroyed()。在surfaceDestroyed我停止遊戲主題通過調用:

@Override 
    public void surfaceDestroyed(SurfaceHolder holder) 
    { 
     synchronized(holder) 
     { 
      renderThread.stop(); 
     } 
    }  

該應用程序去背景罰款。然後,當我按下圖標重新啓動應用程序時,屏幕上會顯示「線程已啓動」消息以及「強制關閉」彈出窗口。當活動在渲染線程上調用start()時進入「surfaceCreated」方法時,會發生此消息。

現在,我看着它幾個小時,想不通這是爲什麼。我相信我的線程在關閉應用程序時停止了,所以我不明白它爲什麼說它已經開始。

回答

8

這些方法不這樣做你認爲他們做的。從API doc

多次啓動線程 永遠不合法。

和:

public final void stop() - 已過時。這種方法本質上是不安全的。

如果你想暫停一個線程,你必須在線程中使用Object.wait()Objecft.notifyAll()

+1

你好,謝謝你的回答。 我在while循環中用join()替換了stop()。 我相信它會在停止線程之前等待。但我仍然有同樣的問題,我錯過了什麼? 至於線程的開始。我知道該線程不能多於一次啓動,因此是錯誤消息。所以你認爲我得到這個錯誤只是因爲線程沒有正確停止? 謝謝 – NioX5199 2010-06-30 10:37:34

+1

@ NioX5199:不,join()不會停止線程,它會等待它自己完成。你得到錯誤,因爲線程已經啓動。線程*不能*被「停止」並重新啓動。正如我寫的:爲了讓一個線程暫停直到條件滿足,您使用Object.wait()。 – 2010-06-30 10:53:04

+0

他也許不應該那樣做。重新創建線程可能是更好的方法。 – alexanderblom 2010-06-30 11:37:20

0

一個壞的解決方案,但它的工作原理..

public void surfaceCreated(SurfaceHolder holder) { 
     try{ 
     _thread.setRunning(true); 
     _thread.start(); 
     }catch(Exception ex){ 
      _thread = new TutorialThread(getHolder(), this); 
      _thread.start(); 
     } 

    } 

改正的熱烈歡迎。

+0

雖然這會起作用(fsvo),但通常不是一個好主意,可以隨時解決問題,然後嘗試糾正。相反,要*積極主動*並給予例外回它們的意義。 – 2013-01-11 00:31:05

5

在我看來,如果你打算經常啓動和停止線程,那麼你不應該把你的代碼打包到線程的子類中(這些例子是因爲它使得代碼更短)。改用Runnable。這樣,您可以在需要時停止並放棄舊的線程,並在需要重新啓動時創建一個新的線程對象來執行Runnable。

private TutorialRunnable tutorialRunnable; 

... 

// Synchronization and error checking omitted for brevity. 
public void surfaceCreated(SurfaceHolder holder) { 
    thread = new Thread(tutorialRunnable); 
    thread.start(); 
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    tutorialRunnable.setRunning(false); 
    while (thread != null) { 
     try { 
      thread.join(); 
      thread = null; 
     } catch (InterruptedException e) { 
     } 
    } 
} 

另外,依靠異常是不好的形式。當你自己的代碼出乎意料地行爲時,這應該作爲最後的手段。