如何在Java中从主线程传递对象到另一个线程

5
在我的主应用程序类中,我有一个JTextArea对象(称为txtArea)。我在main_application程序中创建了另外两个线程。我创建的两个线程是用于读取和写入串口的。现在我想将串口读取缓冲区数据放入JTextArea对象中。所以我需要将在main_application中创建的JTextArea对象传递给read-thread,以便read-thread可以将读取输出放入JTextArea中。
但是这样做后,我遇到了空指针访问问题。当我在main_application中检查JTextArea对象时,它不是null,但是在传递给线程后,我检查它时发现它是null。我不知道这是如何发生的......如果有任何技术大牛可以帮助我,我将非常感激。
谢谢, Surjya

你是如何传递对象的?你能提供几行代码来演示你的问题吗? - Suppressingfire
4个回答

2

如另一个回答所提到的,您只能在Swing线程本身上更改Swing组件的内容。确保所有其他线程都这样做的好方法是不公开实际的JTextArea,而是为其他对象提供从main_application安全添加文本到文本区域的方法,如下所示:

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

这是一个简单的例子,但您可以根据需要进行扩展。由于它附加了两个不可变字符串,因此这也使用了更昂贵的添加文本方式。您可以使用JTextArea.getDocument()检索模型,然后使用文档中的变异方法更有效地更新文本。但是,通过提供像这样的方法,您可以在不影响其他线程或对象的情况下将其实现更改。

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

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


1

在线程之间共享对象可能会变得非常混乱,您可能想阅读有关Actor模型的内容以获得不同的方法。特别是在GUI领域,Model-View-Controller方法可以帮助解决问题。

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

public static JTextArea TXTAREA

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

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


TXTAREA 应该是易失性的吗?(免责声明:我还没有阅读《Java并发实践》,但这在我的待办事项列表中 :)) - wds

0

0
  1. 将JTextArea引用发布到另一个线程是不正确的,因为Swing组件是基于MVC模式(实际上是model-ui)。因此,您使用Swing组件的一般方式是更新它们的模型并让视图(ui)显示更改;
  2. 另一个要点是,大多数Swing组件都不是线程安全的,即如果您从除EDT之外的线程使用Swing组件,则无法确保应用程序正常工作;

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接