2010-12-19 13 views
6

he encontrado un problema misterioso con un código de Java para hacer la tarea. Un programa de amigo una aplicación que esta al principio:de Java no se rompe cuando, cuando se ejecuta en Linux

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

El 'fin' booleano es falso, mientras que toda la ejecución y cuando el usuario sale de la aplicación sucede esto:

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

El println muestra como el valor de 'end' cambia a verdadero y lógicamente en la computadora de mi amigo (MacOS) mientras termina y la aplicación también.

El problema es que en mi computadora (Ubuntu Linux) el println también muestra como el valor cambia pero el tiempo no termina (nunca se llega al println "Finish"). Lo gracioso es si ponemos impresiones en el momento ... ¡entonces funciona!

+4

en cuenta que no debe utilizar oscilación (o en la práctica AWT) de la rosca de distribución de eventos AWT (EDT). –

Respuesta

3

end debe ser volatile desde sus compartida entre dos hilos!

+0

Gracias, esto resuelve el problema :) Te señalé como resuelto porque creo que eras la primera respuesta. No sé si es la forma de hacerlo. – davidgnin

+0

Fui el primero en unos 17 segundos, pero eso es justo ;-) – Lucero

+0

:) ¡Sí! ¡Yo gano! :) – dacwe

2

Se ve como una cuestión de roscado.

Try declarar end como volatile, o mejor aún, utilizar un CountDownLatch ya que esto evita acaparando una 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(); 
    } 
} 

Nota el uso de invokeAndWait para cambiar la visibilidad de la ventana de un hilo no EDT.

+0

¿Por qué la necesidad de un CountDownLatch? ¿Por qué no solo Object.wait()? –

+0

El volátil funciona, y lamentablemente no tengo tiempo ahora para probar CountDownLatch, pero lo intentaré pronto. – davidgnin

+0

@Sergey Tachenov, 'Object.wait' es un método de bajo nivel y tiene dificultades, p. 'notify'-vs-'notifyAll', activación espuria. Puedes evitarlo, pero entonces estarías reinventando la rueda. – finnw

5

Varias otras personas han mencionado que debe ser volátil. Una cosa que nadie parece haber mencionado todavía es que usted está "ocupado esperando", lo cual es incorrecto, incorrecto, erróneo. Si desea esperar que ocurra algo en otro hilo, debe usar los bloqueos de sincronización o Semaphores.

+0

+1 - buen punto. – Lucero

Cuestiones relacionadas