2010-09-12 97 views
2

我遇到以下問題。我的J2ME應用程序完全死機。雖然這是一個僵局,但是使用NetBeans的內置功能,它找不到這樣的功能。Java中的線程問題

過了一段時間但是,它開始在控制檯拋出以下消息:

8242276 - CORE - CRITICAL - 2 - **event queue 3 full, dropping event
8242284 - CORE - CRITICAL - 2 - **event queue 3 full, dropping event
8242292 - CORE - CRITICAL - 2 - **event queue 3 full, dropping event
8242340 - CORE - CRITICAL - 2 - **event queue 3 full, dropping event
8242540 - CORE - CRITICAL - 2 - **event queue 3 full, dropping event
8242628 - CORE - CRITICAL - 1 - **event queue 3 full, dropping event
8242636 - CORE - CRITICAL - 1 - **event queue 3 full, dropping event
8242644 - CORE - CRITICAL - 1 - **event queue 3 full, dropping event

等等。

任何想法,如果它是而不是死鎖(在NetBeans的說明如此),將不勝感激。

謝謝!

回答

2

當您使用AWT或Swing時,會在後臺運行一個特殊線程,稱爲EventQueue。當你將一個監聽器添加到一個組件(比如ActionListener到JButton)和事件監聽器方法(比如actionPerformed)時,該方法在EventQueue線程上執行。您可以選擇到EventQueue線程上執行的東西時,當前線程是無法通過運行

EventQueue.invokeLater(new Runnable(){ //this could also be SwingUtilities.invokeLater() instead 
    public void run(){ 
     ... 
    } 
}); 

這是偉大的EventQueue上線。當你一遍又一遍地發生一個事件時,問題就來了。發生這種情況時,EventQueue線程無法足夠快地爲前一個事件執行代碼,以執行下一個事件的代碼。所以它將事件放入隊列中,等待當前的事件處理程序完成。當您在EventQueue線程上執行大型操作時(例如從文件讀取),可能會發生這種情況。例如:

ActionListener l = new ActionListener(){ 
    public void actionPerformed(ActionEvent ae){ 
     try { 
      BufferedReader in = new BufferedReader(new FileReader("foo.txt")); 
      StringBuffer sb = new StringBuffer(); 
      char[] buf = new char[4096]; 
      int n; 
      while (-1 != (n = in.read(buf))){ 
       sb.append(buf, 0, n); 
      } 
      in.close(); 
      String s = sb.toString(); 
      jTextPane1.setText(s); 
     } catch (IOException ioe){ 
      ioe.printStackTrace(); 
     } 

    } 
}; 
jButton1.addActionListener(l); 

actionPerformed所有代碼都是EventQueue中線程上執行。在代碼完成之前,不能處理其他事件。如果foo.txt是一個大文件,那麼在代碼完成之前還需要一段時間。這意味着每次在代碼完成之前單擊jButton1時,它都會將新事件添加到EventQueue。所以如果你反覆點擊jButton1,那麼會有越來越多的事件添加到隊列中。你不能以這種方式溢出,因爲你不能夠快速點擊,並且不會放棄足夠長的時間。但是,如果鼠標移動等事件發生在每個像素處,則會導致重大事件。然後,這可能會導致一個巨大的EventQueue隊列,甚至可能導致EventQueue溢出。解決此問題的一種方法可能是在事件發生後立即啓動另一個線程。例如:

final Runnable r = new Runnable() { 
    public void run() { 
     try { 
      BufferedReader in = new BufferedReader(new FileReader("foo.txt")); 
      StringBuffer sb = new StringBuffer(); 
      char[] buf = new char[4096]; 
      int n; 
      while (-1 != (n = in.read(buf))) { 
       sb.append(buf, 0, n); 
      } 
      in.close(); 
      final String s = sb.toString(); 
      EventQueue.invokeLater(new Runnable(){ 
       public void run(){ 
        jTextPane1.setText(s); 
       } 
      }); 
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 
    } 
}; 
ActionListener l = new ActionListener(){ 
    public void actionPerformed(ActionEvent ae){ 
     new Thread(r).start(); 
    } 
}; 
jButton1.addActionListener(l); 

有必要的理由來調用EventQueue中的線程上的東西,比如在

EventQueue.invokeLater(new Runnable(){ 
    public void run(){ 
     jTextPane1.setText(s); 
    } 
}); 

是因爲否則屏幕不會被更新。例如,如果維護進度條,EventQueue.invokeLater()會立即更新屏幕,但是如果未包裝在EventQueue.invokeLater()中,則它將等待直到線程完成,然後更新屏幕。當談到進度條時,這是毫無用處的。在這種情況下,它可能沒有太大的作用。

Thanx爲一個偉大的問題!

+0

感謝您的回答!你很徹底。我的問題是關於Java ME,而不是Java SE。然而,使用EventQueue的想法在兩者中看起來都是一樣的。不幸的是,答案仍然不能解決我目前的** J2ME **問題。我會忍受你所說的話,並會嘗試自己解決它。 – 2010-09-12 15:16:18

+0

好吧,這是一個僵局,即使NetBeans找不到一個。 – 2010-09-12 16:18:22