代码之家  ›  专栏  ›  技术社区  ›  Surjya Narayana Padhi

如何将对象从主线程传递到Java中的另一线程

  •  5
  • Surjya Narayana Padhi  · 技术社区  · 14 年前

    在我的主应用程序类中,我有一个jTextArea对象(比如txtArea)。我在主应用程序中创建了另外两个线程。我创建的两个线程用于在串行端口中读写。现在,我想将串行端口读取缓冲区数据放入JTextArea对象中。所以我需要将在主应用程序中创建的jtexArea对象传递给read线程,以便read线程可以将read输出传递给jtexArea。

    但是这样做之后,我面临着空指针访问问题。当我检查主应用程序中的jTextArea对象时,它不是空的,但是在传递到线程之后,我检查了它的空。我不知道它是怎么发生的……如果有极客能帮我,我会很高兴的……

    谢谢, 苏利亚

    4 回复  |  直到 14 年前
        1
  •  1
  •   John Paulett    14 年前

    在线程之间共享对象会变得非常混乱,您可能需要阅读 Actor model 换一种方法。特别是在GUI竞技场中, Model-View-Controller 接近代码帮助。

    但回到问题上来,您可以通过将JTextArea设置为静态变量并让所有不同的线程随意修改静态实例来快速破解它:

    public static JTextArea TXTAREA
    
    void main_application(){
        //set up app
        ...
        TXTAREA = new JTextArea()
        ...
    }
    

    然后在串行读取线程中,将文本设置为 TXTAREA . 这个解决方案不理想,我认为一个更好的方法是使用MVC方法,并有一个控制器,它接受将值放入文本区域。

        2
  •  2
  •   Kevin Brock    14 年前

    正如在另一个响应中提到的,您只能更改回转线程本身上回转组件的内容。确保所有其他线程都这样做的一个好方法是不公开实际的JTextArea,而是为其他对象提供一种安全的方法来从主应用程序向文本区域添加文本,例如:

    public class main_application {

    private JTextArea txtArea;
    
    public void addText(final String txt) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                txtArea.setText(txtArea.getText() + txt);
            }
        });
    }
    

    }

    这是一个简单的例子,但是您可以根据需要在此基础上进行扩展。这还使用了一种更昂贵的方式来添加文本,因为它附加了两个不可变的字符串。可以使用jtexarea.getdocument()检索模型,然后使用文档中的突变方法更有效地更新文本。但是,通过提供这样的方法,您可以在将来更改实现,而不会影响其他线程或对象。

    注意参数 TXT 是最终的,这是必需的,以便可以在匿名内部类中直接引用它。

    您可能希望将其与主应用程序类分离,并为要从其他线程操作文本区域的方法/方法创建接口或类,然后将包装此文本区域的对象交给它们。

        3
  •  0
  •   Jonathan Holloway    14 年前

    查看同步队列:

    http://java.sun.com/javase/6/docs/api/java/util/concurrent/SynchronousQueue.html

    它将允许您将对象存储到队列中,然后等待对象被删除。

        4
  •  0
  •   denis.zhdanov    14 年前
    1. 将JTextArea引用发布到另一个线程是不正确的,因为Swing组件是基于MVC的(实际上是模型UI)。因此,使用Swing组件的一般方法是更新它们的模型并让View(UI)显示更改;
    2. 另一点是,大多数Swing组件不是线程安全的,也就是说,如果从线程中使用Swing组件,那么您无法确保应用程序正常工作,而不是 EDT ;

    因此,您应该执行以下操作:每当您有新的数据显示时,提交新的任务 文本区 要从EDT执行的内容更新。你可以通过 SwingUtilities.invokeLater()