抛出异常时EDT是否重新启动?

发布于 2024-09-05 23:05:47 字数 1544 浏览 8 评论 0原文

(下面的示例代码是独立且可运行的,您可以尝试一下,它不会使您的系统崩溃:)

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

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 评论的那样,未经检查的异常“被捕获、转储,线程继续运行”?

这是怎么回事?

(the example code below is self-contained and runnable, you can try it, it won't crash your system :)

Tom Hawtin commented on the question here: Why do people run Java GUI's on the Event Queue

that:

It's unlikely that the EDT would crash. Unchecked exceptions thrown in EDT dispatch are caught, dumped and the thread goes on.

Can someone explain me what is going on here (every time you click on the "throw an unchecked exception" button, a divide by zero is performed, on purpose):

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 get the following message (which is what I'd expect):

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

and to me this is an unchecked exception right?

You can see that the thread ID is getting incremented every time you trigger the crash.

So is the EDT automatically restarted every time an unchecked exception is thrown or are unchecked exceptions "caught, dumped and the thread goes on" like Tom Hawtin commented?

What is going on here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

囍笑 2024-09-12 23:05:47

有趣的问题。我本以为异常被捕获并且线程继续,但经过一些研究后我不太确定。

我用一个收集了所有“看到的”awt 线程的程序扩展了你的程序

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

,每次单击“抛出异常”按钮时,集合的大小都会增加,这似乎表明在出现异常情况时会初始化一个新线程。例外。

最后我在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.
 */

完整的run方法的实现如下所示:

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

Interesting question. I would have thought that the exceptions were caught and that the thread went on, but after some research I'm not so sure.

I extended your program with a

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

in which I collected all "seen" awt threads, and the size of the set increases each time I click the "throw exception"-button, which seems to suggest that a new thread is initialized in case of an exception.

Finally I found this comment in the run implementation of 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.
 */

The implementation of the complete run method looks like:

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);
        }
    }
}
涙—继续流 2024-09-12 23:05:47

作为参考,“此机器的特定行为 取决于实现。”例如,线程 ID 在我的平台上保持不变。最终效果,在 AWT 线程问题 是“当至少有一个可显示组件时,JVM 将不会退出”。

For reference, "The particular behavior of this machinery is implementation-dependent." For example, the thread ID remains unchanged on my platform. The net effect, discussed in AWT Threading Issues, is that "the JVM will not exit while there is at least one displayable component."

猫烠⑼条掵仅有一顆心 2024-09-12 23:05:47

有一个默认的 UncaughtExceptionHandler在事件调度线程上设置,它将异常打印到 System.out,然后在线程中继续。

There is an default UncaughtExceptionHandler set on the Event Dispatch Thread, which prints the Exception to System.out and then continues in the Thread.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文