1

ここで単純なものが欠けていると確信していますが、それを見ることはできません。フラグを使用してスレッドを終了し、それを結合してきれいにクリーンアップしていますが、結合が終了せず、待機するだけです。現在、スレッドの実行ループには何もないため、別のループでスタックすることはありません。

スレッド:

package com.nox.willywars;

public class GameThread extends Thread {

//{{Variables
private boolean running;
//}}

//{{Getters/Setters
public void setRunning(boolean running) {
    this.running = running;
}
//}}

//{{Constructor
public GameThread() {
    running = false;
}
//}}Constructor

//{{Public methods
@Override
public void run() {
    while(running) {
        ///...CODE GO HERE
    }
}

public boolean isRunning() {
    return running;
}
//}}
}

停止に失敗するコード:

//{{Lifecycle methods
@Override
public void create() {
    //LOAD! Probably debug temp
    TileFactory.load();

    mapScreen = new MapScreen();
    setScreen(mapScreen);

    gameThread = new GameThread();
    gameThread.setRunning(true);
    gameThread.start();
}

@Override
public void resize(int width, int height) {
}

@Override
public void pause() {
    killGameThread();
}

private void killGameThread() {
    if(gameThread != null) {
        if(gameThread.isAlive() && gameThread.isRunning()) {
            gameThread.setRunning(false);
            boolean retry = true;
            while(retry) {
                try {
                    gameThread.interrupt();
                    gameThread.join();
                    retry = false;
                } catch (InterruptedException e) {}
            }
        }
    gameThread = null;
    }
}
//}}

現在、gameThread.join() に到達し、そこでスタックして、スレッドが終了するのを待っています。ここで何か不足していますか?私が理解しているように、runningがfalseに設定されるとスレッドは終了し、すでに停止しているため、正常に参加するはずです。

編集: GameThread を実行するクラスからいくつかのコードを追加しました。Pause() は、KillGameThread が実行される場所です。揮発性を実行しましたが、効果はありませんでした。私は別の奇妙な症状も見つけました: GameThread が動かなくなったときに何が入っているかを調べることを提案した人もいるので、デバッガーに入りました。join() がスタックしている間、私は GameThread スレッドを一時停止し、それが (running) 中にオンになっていることを確認しました。running は間違いなく false でした。次に、コードをステップオーバーすると、ループを終了して正しく終了しました。これは、デバッグが原因のようです。スレッドが何らかの理由で中断されているようです。

4

3 に答える 3

3

最初に実行フラグを揮発性として設定します

private volatile boolean running;

ゲーム スレッドは正確には何をしますか。何らかの I/O 操作によってブロックされている可能性があります。
ゲームスレッドがスリープ/待機/参加しない場合は、中断しても意味がありません。
ゲーム スレッド コードを共有する必要があります。

于 2013-10-28T09:38:30.853 に答える
1

user2511414が指摘したように、 を使用してみてくださいvolatile。つまり、これにより、値 odrunningが常にキャッシュされずに直接アクセスされるようになります。

それを設定volatileしても状況は解決しません。彼の問題は、おそらくGameThread#runコメントアウトしたメソッドのコードセクションにあります。

jstackまたはを使用して、参加しようとしているスレッドのスレッド ダンプjvisualvmを取得できます。これにより、少なくともどこにぶら下がっているかが示され、解決策につながる可能性があります。

于 2013-10-28T09:37:59.517 に答える
1

runningフラグが正しく同期されていません。これにより、(理論的には) スレッドが状態の変化に気付かない可能性があります... Java メモリモデルの動作方法が原因です。として宣言するかvolatile、同期されたメソッド呼び出し (または同期されたブロック) で常にアクセスして更新する必要があります。

しかし(IMO)本当の問題は、スレッドに停止するように指示している方法(実際には方法)にあり、スレッドがチェックまたは応答しています。

  • フラグを使用してスレッドに停止を指示する場合、スレッドはそのフラグを頻繁にチェックする必要があります。スレッドがチェックの間に何か他のことをするのに無期限に長い時間を費やす可能性がある場合、停止する必要があることに気付かない可能性があります。

  • 次に使用するThread.interrupt()場合:

    • コードはThread.isInterrupted()、アドホック フラグではなく、スレッドの「中断」ステータスをテストするために呼び出す必要があります。さらに、定期的にステータスをテストする必要があります。

    • コードは、InterruptedExceptionand をInterruptedIOException適切に処理する必要があります。これはコール スタック全体に適用されます。

ほとんどの場合、呼び出しは実際にはスレッドを中断Thread.interrupt()しないことに注意してください。ほとんどの場合、手動でテストする必要があるフラグを設定するだけです。それ以上になるのは、特定のブロッキング コールだけです。たとえば、いくつかの IO 呼び出し。Object.wait(...)


これらのことが起こるはずのコードのほとんどが省略されています。私たちが言える最善のことは、問題はあなたが私たちに示していないコードにある可能性が最も高いということです.

于 2013-10-28T10:00:18.493 に答える