我有一个字符串,它将由四个不同的线程以不可预测的顺序访问。
String s = "When value is";
现在上面的字符串将由四个不同的线程通过 Java Swing EDT 进行更新。我有两个 JCombobox 和两个 JTextField。在这些组件的事件处理程序内部,我必须更新上面的字符串。
例如 当文本字段焦点更改时字符串应为“当值为 X 时” 当组合更改时字符串应为“当值小于 X 和 Y 时”
就像上面一样,四个线程将更改一个字符串。如果我不控制它们,输出就会出乎意料。解决这个问题的最佳方法是什么。我可以使用 join() 或可能使用 volatile,但这会使代码变得复杂。
请分享您的想法。提前致谢。
最佳答案
首先,String
是不可变的,因此无法更新。然而,另一个对象(例如 Swing 组件)可能保存对 String 的引用,并且可以更新该引用以指向不同的 String 。这是在 GUI 中更新文本时通常会发生的情况。
如果您有四个不同的线程需要更新 Swing 组件,例如要显示不同的 String
,他们应该通过使用 SwingUtilities
方法 invokeLater
对要在单个事件调度线程上运行的任务进行排队来完成此操作,或者invokeAndWait
,例如
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myComponent.setText("New string");
}
};
或者在更复杂的应用程序中,您可能想要更新一个域对象,该域对象需要在这四个线程中都是线程安全的,然后单独更新 EDT 上的 Swing 组件。在我看来,创建线程安全代码并不容易。我强烈推荐这本书Java Concurrency in Practice ,但要点是确保一次只有一个线程执行涉及暂时处于不一致状态的相关对象的任何操作。有时可以通过适当使用现有的线程安全类和原子操作来实现这一点,但可能需要使用锁,通常是通过同步
方法或 block 。
当然,如果您根本没有四个线程,而只有在 EDT 上调用的四个事件处理程序(现在看来),那么这些都无关紧要。
关于Java多线程访问一个String,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6760943/