3

これは、コードが実行すべき内容に従わないと思うコードのスニペットです。

public void updateTimeElapsed() {
    timeElapsedLabel.setText("Time elapsed: " + ((System.nanoTime() - time) / Math.pow(10, 9)));
}

public void updateTimeElapsedIndefinitely() {
    while (true) {
        //System.out.println("Hi");
        //TODO: Why this no work?
        if (start) { System.out.println("Shoulda'"); updateTimeElapsed(); }
    }
}

コメントしたら

System.out.println("Hi")

コードは明らかに機能しません。コメントを外すと、コメントが削除されます。

注:ゲームを開始するために「s」を押すとすぐに開始は真になります。ただし、このメソッドは最初に呼び出されるため、「s」キーを押すまで「hi」が何度も無期限に表示されます。

写真には千の言葉が書かれているので、私が何を意味するのかを説明するために何百もの写真(ビデオ)を提供します: https ://dl.dropbox.com/u/2792692/CodeWeird.ogv

https://dl.dropbox.com/u/2792692/CodeWeird.wmv

誰かが何が起こっているのか教えてもらえますか?

4

2 に答える 2

7

ブール値startが別のスレッドによって更新されているように見えますが、として宣言していないvolatileため、ループは更新された値を確認しません。

printlnを追加して「修正」することは、JVMがコンソールプリンターのネイティブシステムオブジェクトを取得するときにスレッドのスタック状態を管理する方法の奇妙な結果です。修正は、開始を揮発性にするか、それにアクセスするために同期することです。

SCCE:

印刷しない:

public class Testit {

    public static void main(String[] args) {
        busted t = new busted();
        t.start();
        try {
        Thread.sleep(1000L);
        } catch (Exception e) {}
        t.startUpdating();

}

    public static class busted extends Thread {

        private boolean start = false;

        public void startUpdating() {
            start = true;
        }

        @Override
        public void run() {
            updateTimeElapsedIndefinitely();
        }

        public void updateTimeElapsedIndefinitely() {
            while (true) {
                if (start) {
                    System.out.println("Hello");
                }
            }
        }
    }
}

次のように変更して、1秒後にHelloのスパムを開始します。

private volatile boolean start = false;

于 2012-07-19T23:14:59.777 に答える
2

Affeのアイデアは良いものだと思いますが、将来的にはwhile(true)ループの代わりにTimerを使用することをお勧めします。少なくとも私の意見でははるかに優れています。

于 2012-07-19T23:30:29.547 に答える