If there is no body, won’t the while loops in Java check their conditions?
In this example, I have a simple JFrame that contains a JButton. JFrame bound with actionlistener The acitonlistener simply changes a boolean flag that allows 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 "done" and prints once after clicking the button
Waiting Button was clicked!
But 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 that this may not be the right way to wait for an action, but I'm still interested in knowing why Java runs this way
Solution
The most likely reason is that flag [0] = true; It is executed on the UI thread, while while (! Flag [0]) is executed on the main thread
Without synchronization, there is no guarantee that changes made in the UI thread will be visible from the main thread
By adding system out. Println, you will introduce a synchronization point (because the println method is synchronized) and the problem is solved
You can set the flag to a volatile instance or class boolean variable (not an array), or more simply, put any code to be executed on the button pressed in the listener itself
For reference, the code with volatile variable is as follows:
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"); }