Java – when the flag changes in different threads, the loop does not end
See English answer > loop doesn't see changed value without a print statement1
import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.JFrame; public class ThreadWhile implements KeyListener { private boolean flag = false; public static void main(String[] args) { //Set up key listening on a dummy JFrame JFrame frame = new JFrame("Key Detector 9000"); frame.setVisible(true); ThreadWhile tw = new ThreadWhile(); frame.addKeyListener(tw); System.out.println("Looping until flag becomes true..."); while(!tw.flag) { //Commenting the println out makes the loop run forever! System.out.println(tw.flag); } System.out.println("Flag is true,so loop terminated."); System.exit(0); } public void keyPressed(KeyEvent e) { flag = true; System.out.println("flag: " + flag); } public void keyReleased(KeyEvent e) {} public void keyTyped(KeyEvent e) {} }
My understanding is that keypressed methods execute in their own threads, so when I press a key, the variable 'flag' should be set to true, and the while loop running in the main method should end
However, when I run this program, the loop will run forever, even if we can see that the 'flag' variable is correctly set to true! Strangely enough, if I insert a fast system of the 'flag' variable in the while loop out. Println echo, the program behaves correctly, but obviously I don't want to print anything in the loop
I guess this problem may be the result of the java compiler trying to optimize an empty while loop to stop actually checking the 'flag' variable? Is there any suggestion to make this work correctly, or maybe there are some better concurrency based methods to pause the main thread until the keypressed thread executes?
thank you!
Solution
You need to declare the flag volatile, otherwise the compiler can optimize your code and skip reading the flag