2010-06-11 4 views
11

(le code exemple ci-dessous est autonome et runnable, vous pouvez l'essayer, il ne sera pas planter votre système :)Est-ce que l'EDT redémarre ou non lorsqu'une exception est levée?

Tom Hawtin a commenté la question ici: Why do people run Java GUI's on the Event Queue

que:

Il est peu probable que l'EDT tombe en panne. Les exceptions non vérifiées lancées dans l'envoi EDT sont interceptées, exportées et le thread se poursuit.

Quelqu'un peut-il me expliquer ce qui se passe ici (à chaque fois que vous cliquez sur le « jeter une exception non contrôlée » bouton, une division par zéro est effectuée, sur le but):

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 le message suivant (qui est ce que je pense):

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

et moi, c'est une exception non contrôlée non?

Vous pouvez voir que l'ID de thread est incrémenté chaque fois que vous déclenchez le crash.

L'EDT est donc automatiquement redémarré chaque fois qu'une exception non vérifiée est levée ou sont des exceptions non contrôlées "pris, déversé et le thread se poursuit" comme Tom Hawtin a commenté?

Que se passe-t-il ici?

+1

Une note intéressante sur un sujet complètement différent: vous n'avez pas besoin de faire Math.abs (0) pour "tromper" le compilateur pour l'accepter. 0/0 est une expression correcte et lancera également l'exception. [lire plus ...] (http: // stackoverflow.com/questions/2934063/is-1-0-a-legal-expression-java) – aioobe

+0

@aioobe: il il, je sais, je sais, j'ai lu cette discussion ... Mais si avait écrit 0/0 ou 1/0 alors les gens auraient demandé que cette chose compile même :) – NoozNooz42

+0

hahaha ... bon point :-) – aioobe

Répondre

4

Pour référence, « Le comportement particulier de this machinery est dépend de l'implémentation. " Par exemple, l'ID de thread reste inchangé sur ma plate-forme. L'effet net, discuté dans AWT Threading Issues, est que "la machine virtuelle Java ne sortira pas tant qu'il y aura au moins un composant affichable".

+0

@trashgod: Je l'ai seulement essayé sur un système Linux Debian jusqu'à présent :) +1, et ce http://java.sun.com/javase/6/docs/api/java/awt/doc-files/AWTThreadIssues. lien html est excellent! – NoozNooz42

+0

ouais. Je suis sur ubuntu en utilisant Java 6. quel système êtes-vous sur trashgod? – aioobe

+0

@ NoozNooz42: Alors que Mac OS X conserve le même ID, je vois l'incrémentation que vous signalez sur Ubuntu 10.04. – trashgod

5

Question intéressante. J'aurais pensé que les exceptions étaient attrapées et que le fil continuait, mais après quelques recherches je ne suis pas si sûr.

J'ai étendu votre programme avec un

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

où je collectionnais tous « vu » fils de AWT, et la taille de l'ensemble augmente chaque fois que je clique sur le « exception throw » -bouton, qui semble suggère qu'un nouveau thread est initialisé en cas d'exception.

Enfin, je trouve ce commentaire dans la run mise en œuvre 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 mise en œuvre de la méthode d'exécution complète ressemble:

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, c'est intéressant. Ce code vient de Java 7? – NoozNooz42

+0

@ NoozNooz42, non, je pense que c'est 6. Faites-moi savoir si vous découvrez que cela a changé en Java 7 :-) – aioobe

+0

Désolé pour la réponse différée. J'ai utilisé Java 1.6 sur Mac OS X 10.5.8 et Ubuntu 10.04. La source Mac est identique à celle que vous avez montrée. – trashgod

0

Un UncaughtExceptionHandler par défaut est défini dans le thread Dispatch d'événement, qui imprime l'exception à System.out et continue dans le thread.

Questions connexes