java - Java中的线程问题

标签 java multithreading java-me deadlock

我有以下问题。我的 J2ME 应用程序完全死机了。我虽然这是一个死锁,但使用 NetBeans 的内置功能,它找不到这样的东西。

但是一段时间后,它开始在控制台中抛出以下消息:

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

等等。

对于如果不是死锁(至少 NetBeans 这么说)可能会发生什么情况的任何想法,我们将不胜感激。

谢谢!

最佳答案

当您使用 AWT 或 Swing 时,有一个特殊的线程在后台运行,称为 EventQueue。当您向组件添加监听器(例如向 JButton 添加 ActionListener)和事件监听器方法(例如 actionPerformed)时,该方法在 EventQueue 线程上执行。当当前线程不是 EventQueue 线程时,您可以选择在 EventQueue 线程上执行某些操作,方法是运行

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

这太棒了。当你一遍又一遍地举办一个 Activity 时,问题就来了。发生这种情况时,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() 中,那么它将等到线程完成后再更新屏幕。这在进度条方面毫无用处。在这种情况下,它可能没有做太多。

感谢您提出一个很好的问题!

关于java - Java中的线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3695098/

相关文章:

java - LWUIT资源编辑器: Creating a Button

java - 如何实现最近使用的缓存

java - liquibase 中是否有替换功能?

java - 用于格式化的实用程序类

java - 如何让 OS X 在应用程序启动时自动安装 Java 7 而不是 Java 6

java - 代码中的内存泄漏问题

c++ - _beginthread 在父构造函数中

Java/hibernate : how to write DAO code for complex SQLs

c# - 异步任务和简单注入(inject)器生命周期范围

java - J2ME模拟器未显示: Emulator 0 terminated while waiting for it to register