2015-11-30 14 views
6

この例では、JButtonにActionListenerが関連付けられた単純なJFrameがあります。このAcitonListenerは、プログラムが完了できるようにするブール値フラグを変更するだけです。私はJavaでwhileループを実行しても、本体がない場合は条件をチェックしませんか?

while(!flag[0]){ 
    System.out.println("I should do nothing. I am just a print statement."); 
} 

この作品を読むためにwhileループを変更した場合

public class Test { 
    public static void main(String[] args){ 
     final boolean[] flag = new boolean[1]; 
     flag[0] = false; 
     JFrame myFrame = new JFrame("Test"); 
     JButton myButton = new JButton("Click Me!"); 
     myButton.addActionListener(new ActionListener(){ 
      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       System.out.println("Button was clicked!"); 
       flag[0] = true; 
      } 
     }); 
     myFrame.add(myButton); 
     myFrame.setSize(128,128); 
     myFrame.setVisible(true); 
     System.out.println("Waiting"); 
     while(!flag[0]){} 
     System.out.println("Finished"); 
    } 
} 

"完了" これは決して印刷物、およびボタンを1回クリックされた後は、しかし

Waiting 
Button was clicked! 

を印刷します!私はおそらくこれを理解

Waiting 
I should do nothing. I am just a print statement. 
I should do nothing. I am just a print statement. 
.... 
I should do nothing. I am just a print statement. 
Button was clicked! 
Finished 

のようにプリントアウトが見える行動を待つための適切な方法ではありませんが、それにもかかわらず、私は、Javaがこのように動作理由を知ることに興味を持っています。

+6

このhttp://docs.oracle.com/javase/tutorial/uiswing/concurrency/を見てください – 3kings

答えて

7

最も可能性の高い理由は、flag[0] = true;がUIスレッドで実行され、while(!flag[0])がメインスレッドで実行される可能性があります。

同期されていないと、UIスレッドで行われた変更がメインスレッドから見えるという保証はありません。

System.out.printlnを追加すると、(printlnメソッドが​​であるため)同期ポイントが導入され、問題が解決されます。

flagは、揮発性のインスタンスまたはクラスのブール型変数(配列ではありません)にすることができます。または、より簡単には、リスナー自体に押されているボタンに実行するコードを入力することができます。参考のため


、揮発性変数とのコードは次のようになります

private static volatile boolean flag; 
public static void main(String[] args) { 
    JFrame myFrame = new JFrame("Test"); 
    JButton myButton = new JButton("Click Me!"); 
    myButton.addActionListener(new ActionListener() { 
    @Override public void actionPerformed(ActionEvent arg0) { 
     System.out.println("Button was clicked!"); 
     flag = true; 
    } 
    }); 
    myFrame.add(myButton); 
    myFrame.setSize(128, 128); 
    myFrame.setVisible(true); 
    System.out.println("Waiting"); 
    while (!flag) { } 
    System.out.println("Finished"); 
} 
+2

また、 'while(!flag [0]){}'はCPU上で非常に積極的です。私はブールファイナルを宣言しなければならないので、OPはJava 7を使用していると思います。 Java 8では、彼は直接 'boolean volatile 'を使うことができました。 –

+1

@GuillaumeF。ローカルの揮発性変数を宣言することはできません。それはフィールドでなければならないので、Java 7または8では最終的なものである必要はありません。 – assylias

+0

ああ、あなたはローカルの揮発性の制限について正しいです。ありがとう –

関連する問題