2010-06-11 24 views
11

(mã ví dụ dưới đây là khép kín và Runnable, bạn có thể thử nó, nó sẽ không sụp đổ hệ thống của bạn :)Liệu EDT có khởi động lại hay không khi một ngoại lệ được ném ra?

Tom Hawtin nhận xét về vấn đề ở đây: Why do people run Java GUI's on the Event Queue

rằng:

Rất có thể EDT sẽ không hoạt động. Các trường hợp ngoại lệ không được kiểm tra được ném trong công văn EDT bị bắt, bán phá giá và chuỗi tiếp tục.

Ai đó có thể giải thích cho tôi những gì đang xảy ra ở đây (mỗi khi bạn click vào "ném một ngoại lệ được kiểm soát" nút, một chia cho số không được thực hiện, về mục đích):

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

} 

tôi nhận được thông báo sau (đó là những gì tôi mong đợi):

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

và với tôi đây là một ngoại lệ không được kiểm soát phải không?

Bạn có thể thấy rằng ID luồng đang được tăng lên mỗi khi bạn kích hoạt sự cố.

Vì vậy, EDT tự động khởi động lại mỗi lần ngoại lệ không được kiểm soát được ném hoặc không được kiểm tra ngoại lệ "bị bắt, bán phá giá và chuỗi tiếp tục" như Tom Hawtin đã nhận xét?

Điều gì đang xảy ra ở đây?

+1

Một lưu ý thú vị về một vấn đề hoàn toàn khác: Bạn không phải làm Math.abs (0) để "lừa" trình biên dịch chấp nhận nó. 0/0 là một biểu thức ok và cũng sẽ ném ngoại lệ. [đọc thêm ...] (http: // stackoverflow.com/questions/2934063/is-1-0-a-legal-java-expression) – aioobe

+0

@aioobe: anh ấy, tôi biết, tôi biết, tôi đã đọc cuộc thảo luận đó ... Nhưng nếu đã viết 0/0 hoặc 1/0 sau đó mọi người sẽ hỏi rằng điều đó thậm chí còn biên dịch :) – NoozNooz42

+0

hahaha ... tốt điểm :-) – aioobe

Trả lời

4

Để tham khảo, "Các hành vi cụ thể của this machinery là phụ thuộc vào thực hiện. " Ví dụ: ID luồng vẫn không thay đổi trên nền tảng của tôi. Hiệu ứng ròng, được thảo luận trong AWT Threading Issues, là "JVM sẽ không thoát ra khi có ít nhất một thành phần có thể hiển thị".

+0

@trashgod: Tôi chỉ thử trên hệ thống Debian Linux cho đến thời điểm này :) +1 và http://java.sun.com/javase/6/docs/api/java/awt/doc-files/AWTThreadIssues này. liên kết html là công cụ tuyệt vời! – NoozNooz42

+0

vâng. Tôi đang sử dụng ubuntu bằng cách sử dụng java 6. hệ thống nào mà bạn đang dùng trên thùng rác? – aioobe

+0

@ NoozNooz42: Trong khi Mac OS X giữ cùng một ID, tôi thấy số gia tăng mà bạn báo cáo trên Ubuntu 10.04. – trashgod

5

Câu hỏi thú vị. Tôi đã có thể nghĩ rằng các ngoại lệ đã bị bắt và sợi chỉ đi vào, nhưng sau một vài nghiên cứu tôi không chắc lắm.

tôi đã mở rộng chương trình của bạn với một

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

trong đó tôi thu thập tất cả "nhìn thấy" đề AWT, và kích thước của bộ tăng mỗi khi tôi nhấp vào "ngoại lệ ném" -button, mà dường như gợi ý rằng một chuỗi mới được khởi tạo trong trường hợp ngoại lệ.

Cuối cùng tôi thấy nhận xét này trong việc thực hiện run của 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. 
*/ 

Việc thực hiện các phương pháp chạy hoàn toàn trông giống như:

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, điều này thật thú vị. Mã đó là từ Java 7? – NoozNooz42

+0

@ NoozNooz42, không, tôi nghĩ rằng đó là 6. Hãy cho tôi biết nếu bạn phát hiện ra rằng nó đã thay đổi trong java 7 :-) – aioobe

+0

Xin lỗi vì trả lời chậm trễ. Tôi đã sử dụng Java 1.6 trên cả Mac OS X 10.5.8 và Ubuntu 10.04. Nguồn Mac giống với nguồn được hiển thị bởi bạn. – trashgod

0

Có một mặc định UncaughtExceptionHandler đặt trên Chủ đề gửi sự kiện, in ngoại lệ ra System.out và sau đó tiếp tục trong chuỗi.

Các vấn đề liên quan