2010-06-11 14 views
11

(el código de ejemplo a continuación es autónomo y ejecutable, se puede probar, no va a bloquear el sistema :)¿El EDT se reinicia o no cuando se lanza una excepción?

Tom Hawtin comentado en la pregunta aquí: Why do people run Java GUI's on the Event Queue

que:

Es poco probable que se bloquee el EDT. Las excepciones no verificadas arrojadas en el despacho de EDT son capturadas, abandonadas y el hilo continúa.

Alguien me puede explicar lo que está pasando aquí (cada vez que se hace clic en el "una excepción sin control" botón, se realiza una división por cero, a propósito):

import javax.swing.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 

public class CrashEDT extends JFrame { 

    public static void main(String[] args) { 
     final CrashEDT frame = new CrashEDT(); 
     frame.addWindowListener(new WindowAdapter() { 
      public void windowClosing(WindowEvent e) { 
       System.exit(0); 
      } 
     }); 
     final JButton jb = new JButton("throw an unchecked exception"); 
     jb.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       System.out.println("Thread ID:" + Thread.currentThread().getId()); 
       System.out.println(0/Math.abs(0)); 
      } 
     }); 
     frame.add(jb); 
     frame.setSize(300, 150); 
     frame.setVisible(true); 
    } 

} 

I obtendrá el siguiente mensaje (que es lo que cabe esperar):

Exception in thread "AWT-EventQueue-0" java.lang.ArithmeticException:/by zero 

y para mí esto es una excepción no comprobada verdad?

Puede ver que la identificación del subproceso se incrementa cada vez que desencadena el bloqueo.

Entonces, ¿el EDT se reinicia automáticamente cada vez que se lanza una excepción sin marcar o están desmarcadas las excepciones "atrapado, vaciado y el hilo continúa" como comentó Tom Hawtin?

lo que está pasando aquí?

+1

Una nota al margen interesante sobre una cuestión completamente diferente: no tiene que hacer Math.abs (0) para "engañar" al compilador para que lo acepte. 0/0 es una expresión aceptable y arrojará la excepción. [más información ...] (http: // stackoverflow.com/questions/2934063/is-1-0-a-legal-java-expression) – aioobe

+0

@aioobe: he he, lo sé, lo sé, he leído esa discusión ... Pero si hubiera escrito 0/0 o 1/0 entonces la gente habría preguntado si eso estaba compilando :) – NoozNooz42

+0

jajaja ... buen punto :-) – aioobe

Respuesta

4

Como referencia, "El comportamiento particular de this machinery es depende de la implementación ". Por ejemplo, la ID del hilo permanece sin cambios en mi plataforma. El efecto neto, discutido en AWT Threading Issues, es que "la JVM no saldrá mientras haya al menos un componente visualizable".

+0

@trashgod: Hasta ahora solo lo he probado en un sistema Debian Linux :) + y http://java.sun.com/javase/6/docs/api/java/awt/doc-files/AWTThreadIssues. ¡El enlace html es excelente! – NoozNooz42

+0

sí. Estoy en ubuntu usando java 6. ¿En qué sistema estás en trashgod? – aioobe

+0

@ NoozNooz42: Mientras que Mac OS X conserva la misma ID, veo el incremento que informa en Ubuntu 10.04. – trashgod

5

Interesante pregunta. Hubiera pensado que las excepciones fueron atrapadas y que el hilo continuó, pero después de algunas investigaciones no estoy tan seguro.

me ampliado su programa con un

Set<Thread> seenAwtThreads = new HashSet<Thread>(); 

en la que he recogido todas las discusiones AWT "visto", y el tamaño del conjunto aumenta cada vez que hago clic en la "excepción tiro" -botón, lo que parece sugieren que se inicialice un nuevo hilo en caso de una excepción.

fin encontré este comentario en el run implementación de EventDispatchThread:

/* 
* Event dispatch thread dies in case of an uncaught exception. 
* A new event dispatch thread for this queue will be started 
* only if a new event is posted to it. In case if no more 
* events are posted after this thread died all events that 
* currently are in the queue will never be dispatched. 
*/ 

La aplicación del método de ejecución completa se parece a:

public void run() { 
    try { 
     pumpEvents(new Conditional() { 
      public boolean evaluate() { 
       return true; 
      } 
     });  
    } finally { 
     /* 
     * This synchronized block is to secure that the event dispatch 
     * thread won't die in the middle of posting a new event to the 
     * associated event queue. It is important because we notify 
     * that the event dispatch thread is busy after posting a new event 
     * to its queue, so the EventQueue.dispatchThread reference must 
     * be valid at that point. 
     */ 
     synchronized (theQueue) { 
      if (theQueue.getDispatchThread() == this) { 
       theQueue.detachDispatchThread(); 
      } 
      /* 
      * Event dispatch thread dies in case of an uncaught exception. 
      * A new event dispatch thread for this queue will be started 
      * only if a new event is posted to it. In case if no more 
      * events are posted after this thread died all events that 
      * currently are in the queue will never be dispatched. 
      */ 
      /* 
      * Fix for 4648733. Check both the associated java event 
      * queue and the PostEventQueue. 
      */ 
      if (theQueue.peekEvent() != null || 
       !SunToolkit.isPostEventQueueEmpty()) { 
       theQueue.initDispatchThread(); 
      } 
      AWTAutoShutdown.getInstance().notifyThreadFree(this); 
     } 
    } 
} 
+0

+1, esto es interesante. ¿Ese código es de Java 7? – NoozNooz42

+0

@ NoozNooz42, no, creo que es 6. Avíseme si descubre que ha cambiado en java 7 :-) – aioobe

+0

Disculpe las demoras en la respuesta. Usé Java 1.6 tanto en Mac OS X 10.5.8 como en Ubuntu 10.04. La fuente de Mac es idéntica a la que muestra. – trashgod

0

Hay un UncaughtExceptionHandler predeterminado configurado en el subproceso de envío de evento, que imprime la excepción a System.out y luego continúa en el subproceso.

Cuestiones relacionadas