Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do while loops in Java not check their conditions if there is no body?

In this example I have a simple JFrame containing a JButton with an ActionListener tied to it. This AcitonListener just changes a boolean flag that should allow the program to complete.

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

This never prints "Finished", and after the button has been clicked once prints

Waiting
Button was clicked!

However, if I modify the while loop to read

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

This works! The printout looks like

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

I understand this probably isn't the proper way to wait on an action, but nonetheless I am interested in knowing why Java behaves this way.

like image 491
Aroto Avatar asked Nov 30 '15 17:11

Aroto


People also ask

Do while loops check condition?

The do while loop checks the condition at the end of the loop. This means that the statements inside the loop body will be executed at least once even if the condition is never true. The do while loop is an exit controlled loop, where even if the test condition is false, the loop body will be executed at least once.

Do while loop in Java with conditions?

Java do-while loop is used to execute a block of statements continuously until the given condition is true. The do-while loop in Java is similar to while loop except that the condition is checked after the statements are executed, so do while loop guarantees the loop execution at least once.

Can a while loop be empty Java?

Syntax and example of empty while loop in JavaThe above empty loop will be executed until the condition becomes false. Because it is an empty while loop java, it will not return anything when we run the code. Such a loop is a time delay loop. The time delay loop is useful for pausing the program for some time.

Can the while loop not run?

The while loop is not run because the condition is not met. After the running the for loop the value of variable i is 5, which is greater than three. To fix this you should reassign the value before running the while loop (simply add var i=1; between the for loop and the while loop).


1 Answers

The likeliest reason is that flag[0] = true; is executed on the UI thread, whereas while(!flag[0]) is executed on the main thread.

Without synchronization, there is no guarantee that the change made in the UI thread will be visible from the main thread.

By adding the System.out.println you introduce a synchronization point (because the println method is synchronized) and the problem gets solved.

You could make flag a volatile instance or class boolean variable (not an array), or, more simply, put whatever code you want executed on the button being pressed in the listener itself.


For reference, the code with a volatile variable would look like this:

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");
}
like image 168
assylias Avatar answered Sep 19 '22 03:09

assylias