9

私の状況は次のとおりです: Android 用のゲームを構築しています。私のゲームのアクティビティは、ゲーム ロジックとレンダリング用のスレッドを持つカスタム surfaceView で構成されています。アーキテクチャは、Google の Web サイトの LunarLander デモに似ています。

アクティビティが開始されると、surfaceView が作成され、次のメソッドが呼び出されます。

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

ホームボタンを押してゲームを終了すると、onPause() メソッドが呼び出され、それが surfaceDestroyed() を呼び出します。surfaceDestroyed では、次のように呼び出してゲーム スレッドを停止します。

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

アプリは正常にバックグラウンドになります。次に、アイコンを押してアプリを再起動すると、ログに「スレッドは既に開始されています」というメッセージが表示され、画面に「強制終了」ポップアップが表示されます。このメッセージは、レンダー スレッドで start() を呼び出したときに、アクティビティが「surfaceCreated」メソッドに入ったときに発生します。

今、私は何時間も調べましたが、これがなぜなのかわかりません。アプリを閉じるとスレッドが停止していると思うので、スレッドが既に開始されていると表示される理由がわかりません。

4

3 に答える 3

8

それらの方法は、あなたが思っていることをしません。APIドキュメントから:

スレッドを複数回開始することは決して合法ではありません。

と:

public final void stop()- 非推奨。この方法は本質的に安全ではありません。

スレッドを一時停止したい場合は、スレッド内からObject.wait()andを使用する必要がObjecft.notifyAll()あります。

于 2010-06-30T10:22:20.387 に答える
5

私の意見では、スレッドを頻繁に開始および停止する場合は、コードを Thread のサブクラスにパックするべきではありません (コードが短くなるため、例ではそうしています)。代わりに Runnable を使用してください。そうすれば、必要なときに古い Thread を停止して破棄し、新しい Thread オブジェクトを作成して、再度開始する必要があるときに 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) {
        }
    }
}

また、例外に依存することは悪い形です。これは、独自のコードが予期しない動作をする場合の最後の手段として使用する必要があります。

于 2011-11-15T10:55:49.040 に答える
0

悪い解決策ですが、うまくいきます。

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

    }

訂正は大歓迎です。

于 2010-11-29T07:16:36.710 に答える