I found a mysterious problem with a Java code for homework. A friend program an application which this at the beginning :
public void run() {
vm.setVisible(true);
while(!end);
System.out.println("Finish");
vm.setVisible(false);
}
The boolean 'end' is false while all the execution and when the user quits the application this happens:
private class CloseSys implements ActionListener {
public CloseSys() {super();}
public void actionPerformed(ActionEvent e) {
System.out.println("CLOSE SYS");
System.out.println("end: "+end);
end = true;
System.out.println("end: "+end);
}
}
The println shows like the value of 'end' changes to true and logically in my friend's computer (MacOS) the while finish and the application too.
The problem is that in my computer (Ubuntu Linux) the println also shows like the value changes but the while doesn't ends (the "Finish" println is never reached). The funny thing about it is if we put prints into the while... then works!
Several other people have mentioned that it should be volatile. One thing nobody seems to have mentioned yet is that you are "busy waiting", which is wrong, wrong, wrongity wrong. If you want to wait for something to happen in another thread, you should use synchronization locks or Semaphores.
end
must be volatile
since its shared between two threads!
Try to make the end
variable volatile - you've been bitten by a multithreading issue (and you have a multi-core CPU).
Here's some info on that: http://www.javamex.com/tutorials/synchronization_volatile_when.shtml
It looks like a threading issue.
Try declaring end
as volatile
, or better still use a CountDownLatch
as this avoids hogging a CPU:
private CountDownLatch latch;
public void run() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
vm.setVisible(true);
}
});
try {
latch.await();
System.out.println("Finish");
} finally {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
vm.setVisible(false);
}
});
}
} catch (InterruptedException ex) {
System.out.println("Interrupt");
Thread.currentThread().interrupt();
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex);
}
}
private class CloseSys implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("CLOSE SYS");
latch.countDown();
}
}
Note the use of invokeAndWait
to change the window visibility from a non-EDT thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With