هل يعيد تشغيل EDT أم لا عند إلقاء استثناء؟
-
26-09-2019 - |
سؤال
(رمز المثال أدناه مكتفي بذاته وقابل للتشغيل ، يمكنك تجربته ، ولن يعطل نظامك :)
علق توم هاوتين على السؤال هنا: لماذا يدير الناس جافا واجهة غريبة في قائمة انتظار الحدث
الذي - التي:
من غير المحتمل أن تحطم EDT. يتم القبض على استثناءات غير محددة في Dispatch 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
وهذا بالنسبة لي هذا استثناء لم يتم التحقق منه ، أليس كذلك؟
يمكنك أن ترى أن معرف الخيط يتم زيادة في كل مرة تقوم فيها بالتحطم.
لذا ، يتم إعادة تشغيل EDT تلقائيًا في كل مرة يتم فيها إلقاء استثناء غير محدد أو استثناءات غير محددة "اشتعلت ، ملقاة ويستمر الخيط" مثل توم هاوتين علق؟
ما الذي يجري هنا؟
المحلول
للإشارة ، "السلوك الخاص لـ هذه الآلية يعتمد على التنفيذ. "على سبيل المثال ، يظل معرف الخيط دون تغيير على النظام الأساسي الخاص بي. قضايا الخيوط AWT, ، هو أن "JVM لن يخرج بينما يوجد مكون واحد على الأقل قابل للشفاء."
نصائح أخرى
سؤال مهم. كنت أعتقد أنه تم القبض على الاستثناءات وأن الخيط استمر ، لكن بعد بعض الأبحاث لست متأكدًا.
لقد قمت بتوسيع برنامجك مع
Set<Thread> seenAwtThreads = new HashSet<Thread>();
حيث جمعت كل مؤشرات الترابط "شوهد" ، ويزداد حجم المجموعة في كل مرة أقوم فيها بالنقر فوق "استثناء رمي"-ولكن يبدو أنه يشير إلى أن خيط جديد يتم تهيئته في حالة استثناء.
أخيرًا وجدت هذا التعليق في 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);
}
}
}
هناك افتراضي uncaughtexceptionHandler تم تعيينه على مؤشر ترابط إرسال الحدث ، والذي يطبع الاستثناء إلى System.out ثم يستمر في الخيط.