如果没有正文,Java中的while循环不会检查它们的条件吗?

在这个例子中,我有一个简单的JFrame包含一个绑定了ActionListener的JButton.这个AcitonListener只是更改了一个允许程序完成的布尔标志.
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");
    }
}

这永远不会打印“完成”,并且在点击按钮后打印一次

Waiting
Button was clicked!

但是,如果我修改while循环来读取

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

这有效!打印输出看起来像

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会以这种方式运行.

解决方法

最有可能的原因是flag [0] = true;在UI线程上执行,而while(!flag [0])在主线程上执行.

如果没有同步,则无法保证UI线程中所做的更改将从主线程中可见.

通过添加System.out.println,您将引入同步点(因为println方法已同步)并且问题得到解决.

您可以将标志设置为易失性实例或类布尔变量(不是数组),或者更简单地,将要执行的任何代码放在侦听器本身中按下的按钮上.

作为参考,带有volatile变量的代码如下所示:

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");
}

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...