2010-09-12 99 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