Until the loop ends when the flag is changed in another thread

I have a while loop in my main Java program method. The loop is supposed to run until the boolean flag variable is set to true in the keyPressed method (I added the program as KeyListener in the JFrame).

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) {} } 

I understand that keyPressed methods execute in their threads, so it seems that when I press a key, the 'flag' variable should be set to true, and the while loop running in the main method should end.

HOWEVER, when I run this program, the loop runs forever, although we can see that the flag variable is correct! Oddly enough, the program behaves correctly if I insert a quick echo message System.out.println of the variable 'flag' inside the while loop, but obviously I don't want to print anything in the loop.

I assume this problem may be the result of a Java compiler trying to optimize an empty while loop until it stops actually checking the 'flag' variable? Does anyone have any suggestions for working correctly on this product, or perhaps even more elegant approaches based on using w390 to pause the main thread until the keyPressed stream being executed is executed?

Thanks!

+6
source share
3 answers

You need to declare the flag volatile , otherwise the compiler may optimize your code and skip reading the flag.

+9
source

While the volatile solution others have suggested should work if you don't need code in the while loop to run continuously, you should instead use wait() and notify() (or notifyAll() ) inside the synchronized section ( to avoid "waiting"). Sort of:

 public class ThreadWhile implements KeyListener { private boolean flag = false; private Object flagLock = new Object(); 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("Waiting until flag becomes true..."); synchronized (tw.flagLock) { while(!tw.flag) tw.flagLock.wait(); // Note: this suspends the thread until notification, so no "busy waiting" } System.out.println("Flag is true, so loop terminated."); System.exit(0); } public void keyPressed(KeyEvent e) { synchronized (flagLock) { flag = true; System.out.println("flag: " + flag); flagLock.notifyAll(); } } ... 

Otherwise, you repeatedly spend cycles on the main thread, checking the flag value again and again (which, in general, if this happens enough, can slow down the processor for other threads and can wear out the battery on mobile devices). This is exactly the situation for which wait() was developed.

+4
source

1 .. You need to use the volatile keyword for the flag, because when we call volatile in the Instance variable , as shown by the JVM, make sure that the stream has to match its own copy of this instance variable with the one stored in memory .

2. Volatile will also help prevent cache values ​​in the stream .

3. Volatile will cause this variable to display the changed value in one thread on another, but DOES NOT prevent the race condition .

4 .. So use the syntax keyword for Atomic statements that set the flag value.

For instance:

 public void keyPressed(KeyEvent e) { synchronized(this){ flag = true; System.out.println("flag: " + flag); } } 
0
source

Source: https://habr.com/ru/post/921040/


All Articles