2010-06-11 27 views
11

(下面的示例代码是自包含的,可运行的,你可以尝试,它不会造成系统崩溃:)当引发异常时,EDT是否重新启动?

汤姆Hawtin评论的问题在这里:Why do people run Java GUI's on the Event Queue

说:

EDT不太可能会崩溃。在EDT调度中抛出的未经检查的异常被捕获,抛弃并且线程继续。

有人可以解释我是怎么回事就在这里(你点击每次“抛出一个未经检查的异常”按钮,执行零一分,故意):

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

} 

我得到以下消息(这是我所期望的):

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

对我来说这是一个未经检查的异常吗?

您可以看到每次触发崩溃时线程ID都会增加。

因此,EDT每次都会自动重新启动一个未经检查的异常或未经检查的异常“被捕获,倾销和线程继续”像Tom Hawtin所评论的那样?

这是怎么回事?

+1

关于完全不同的问题的一个有趣的注意事项:您不必执行Math.abs(0)来“欺骗”编译器接受它。 0/0是一个好的表达式,并且还会抛出异常。 [阅读更多...](http:// stackoverflow。com/questions/2934063/is-1-0-a-legal-java-expression) – aioobe 2010-06-11 07:28:52

+0

@aioobe:他他,我知道,我知道,我已经读过那个讨论......但是如果写了0/0或1/0,那么人们会问这是甚至编译:) – NoozNooz42 2010-06-11 07:37:35

+0

haha​​ha ...好点:-) – aioobe 2010-06-11 07:39:01

回答

4

供参考“的this machinery的特定行为是依赖于实现“。例如,线程ID在我的平台上保持不变。在AWT Threading Issues中讨论的净效果是“当有至少一个可显示组件时,JVM不会退出”。

+0

@trashgod:我只在Debian Linux系统上试过它+1,还有那个http://java.sun.com/javase/6/docs/api/java/awt/doc-files/AWTThreadIssues。 HTML链接是优秀的东西! – NoozNooz42 2010-06-11 07:31:55

+0

是的。我在使用Java 6的Ubuntu上。哪个系统在垃圾桶上? – aioobe 2010-06-11 07:36:03

+0

@ NoozNooz42:虽然Mac OS X保持相同的ID,但我看到您在Ubuntu 10.04上报告的增量。 – trashgod 2010-06-11 07:39:17

5

有趣的问题。我会认为,例外被捕获,线程继续,但经过一些研究,我不太确定。

我有

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

中,我收集了所有“看见” AWT线程扩展程序,以及集的大小,每次我点击“抛出异常”按钮上,这似乎增加建议在发生异常时初始化新线程。

最后我发现,在run实施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. 
*/ 

完整运行方法的实现是这样的:

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,这很有趣。该代码来自Java 7? – NoozNooz42 2010-06-11 07:29:19

+0

@ NoozNooz42,不,我认为它是6.让我知道,如果你发现它已经改变了Java 7 :-) – aioobe 2010-06-11 07:34:53

+0

对不起,延迟回复。我在Mac OS X 10.5.8和Ubuntu 10.04上都使用了Java 1.6。 Mac的来源与您所显示的相同。 – trashgod 2010-06-11 08:03:42

0

在事件派发线程上设置了一个默认的UncaughtExceptionHandler,它将System.out的Exception打印出来,然后在Thread中继续。

相关问题