2010-12-19 8 views
6

Ich habe ein mysteriöses Problem mit einem Java-Code für Hausaufgaben gefunden. Ein Freund Programm eine Anwendung, die diese am Anfang:Java bricht nicht, wenn es unter Linux läuft

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

Die boolean ‚end‘ falsch ist, während alle die Ausführung und wenn der Benutzer die Anwendung beendet wird dies geschieht:

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

Die println zeigt wie Der Wert von "Ende" ändert sich im Computer meines Freundes (MacOS) und währenddessen und auch in der Anwendung zu "Wahr" und "logisch".

Das Problem ist, dass in meinem Computer (Ubuntu Linux) die println auch wie der Wert ändert, aber die while nicht endet (die "Finish" println wird nie erreicht). Das lustige daran ist, wenn wir in die Weile Prints hineinlegen ... dann funktioniert es!

+4

Hinweis: Sie sollten Swing (oder in der Praxis AWT) nicht vom AWT Event Dispatch Thread (EDT) verwenden. –

Antwort

3

endvolatile seit ihrer gemeinsamen zwischen zwei Threads sein muss!

+0

Danke, das löst das Problem :) Ich markiere dich als gelöst, weil ich denke du warst die erste Antwort. Ich weiß nicht, ob es so ist. – davidgnin

+0

Ich war der erste nach ca. 17 Sekunden, aber das ist schon gut ;-) – Lucero

+0

:) Ja! Ich gewinne! :) – dacwe

2

Es sieht wie ein Threading-Problem aus.

Try end als volatile erklären, oder besser noch ein CountDownLatch verwenden, da dies eine CPU vermeidet hogging:

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

Beachten Sie die Verwendung von invokeAndWait das Fenster Sichtbarkeit von einem Nicht-EDT Thread zu ändern.

+0

Warum die Notwendigkeit eines CountDownLatch? Warum nicht einfach Object.wait()? –

+0

Das volatile funktioniert, und leider habe ich jetzt keine Zeit, das CountDownLatch auszuprobieren, aber ich werde es bald versuchen. – davidgnin

+0

@Sergey Tachenov, "Object.wait" ist eine Low-Level-Methode und hat Tücken, z.B. 'notify'-vs-' notifyAll', fälschlicher Weckruf. Du kannst es umgehen, aber dann erfindest du das Rad neu. – finnw

5

Mehrere andere Leute haben erwähnt, dass es flüchtig sein sollte. Eine Sache, die noch niemand erwähnt zu haben scheint, ist, dass Sie "beschäftigt" sind, was falsch, falsch oder falsch ist. Wenn Sie warten möchten, dass in einem anderen Thread etwas passiert, sollten Sie Synchronisierungssperren oder Semaphores verwenden.

+0

+1 - guter Punkt. – Lucero

Verwandte Themen