Перезапускается ли EDT или нет при возникновении исключения? - PullRequest
11 голосов
/ 11 июня 2010

(приведенный ниже пример кода является автономным и работоспособным, вы можете попробовать его, он не сломает вашу систему:)

Том Хотин прокомментировал вопрос здесь: Почему люди запускают графический интерфейс Java в очереди событий

, что:

Маловероятно, что 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 автоматически перезапускается каждый раз, когда неконтролируемое исключениевыброшенные или непроверенные исключения "перехвачены, сброшены и поток продолжается" , как прокомментировал Том Хотин?

Что здесь происходит?

Ответы [ 3 ]

5 голосов
/ 11 июня 2010

Интересный вопрос. Я бы подумал, что исключения были перехвачены и что цепочка продолжилась, но после некоторых исследований я не уверен.

Я расширил вашу программу с

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);
        }
    }
}
4 голосов
/ 11 июня 2010

Для справки: «Особое поведение этого механизма зависит от реализации». Например, идентификатор потока остается неизменным на моей платформе. Общий эффект, обсуждаемый в AWT Threading Issues , заключается в том, что «JVM не завершит работу, пока есть хотя бы один отображаемый компонент».

0 голосов
/ 02 февраля 2011

По умолчанию установлен поток UncaughtExceptionHandler , который печатает исключение в System.out и затем продолжает работу в потоке.

...