Java ne casse pas un moment lorsqu’il est exécuté sous Linux

J’ai trouvé un problème mystérieux avec un code Java pour les devoirs. Un ami programme une application que celle-ci au début:

public void run() { vm.setVisible(true); while(!end); System.out.println("Finish"); vm.setVisible(false); } 

Le booléen ‘end’ est faux pendant toute l’exécution et lorsque l’utilisateur quitte l’application, cela se produit:

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

Le println montre comme la valeur de ‘end’ des changements à true et logiquement dans l’ordinateur de mon ami (MacOS), à la fin de l’application et à l’application également.

Le problème est que dans mon ordinateur (Ubuntu Linux), println montre également que la valeur change, mais le temps ne se termine pas (le println “Finish” n’est jamais atteint). Ce qui est amusant, c’est que si on met des tirages dans le temps, alors ça marche!

end doit être volatile car il est partagé entre deux threads!

Plusieurs autres personnes ont mentionné qu’il devrait être volatil. Une chose que personne ne semble avoir encore mentionnée, c’est que vous êtes “occupé à attendre”, ce qui est faux, faux, faux. Si vous voulez attendre que quelque chose se produise dans un autre thread, vous devez utiliser des verrous de synchronisation ou des sémaphores .

Essayez de rendre la variable de end volatile – vous avez été mordu par un problème de multithreading (et vous avez un processeur multicœur).

Voici quelques informations à ce sujet: http://www.javamex.com/tutorials/synchronization_volatile_when.shtml

Cela ressemble à un problème de threading.

Essayez de déclarer end comme étant volatile , ou mieux encore, utilisez CountDownLatch car cela évite de forcer un 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(); } } 

Notez l’utilisation de invokeAndWait pour modifier la visibilité de la fenêtre à partir d’un thread non-EDT.