抛出exception时EDT是否重启?

(下面的示例代码是自包含且可运行的,您可以尝试它,它不会崩溃您的系统:)

Tom Hawtin在这里评论了这个问题: 为什么人们在事件队列上运行Java GUI

那:

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

有人可以解释我在这里发生了什么(每次你点击“抛出一个未经检查的exception”按钮,有意地执行除以零):

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都会增加。

每次抛出未经检查的exception时,EDT会自动重启,还是未经检查的exception“捕获,转储和线程继续”,如Tom Hawtin评论的那样?

这里发生了什么?

作为参考,“ 这种机器的特殊行为取决于实现。” 例如,线程ID在我的平台上保持不变。 在AWT线程问题中讨论的净效应是“当至少有一个可显示组件时,JVM不会退出”。

有趣的问题。 我本以为抓住了exception并且线程继续进行,但经过一些研究我不太确定。

我用一个扩展你的程序

 Set seenAwtThreads = new HashSet(); 

我收集了所有“看到”的awt线程,每次单击“抛出exception”按钮时,集合的大小都会增加,这似乎表明在exception的情况下初始化了一个新线程。

最后,我在EventDispatchThreadrun实现中找到了这条评论:

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

在Event Dispatch Thread上设置了一个默认的UncaughtExceptionHandler ,它将Exception输出到System.out,然后继续在Thread中。