2010-09-04 46 views
2

我不清楚线程约束。 在秋千中,所有的gui组件都必须通过EDT进行更新。 SwingWorker在Java6中提供了长时间的操作,在完成的方法中可以更新gui组件。我的理解是,done()方法中的gui组件会在EDT中更新。因此应该没有同步问题。但这里link text线程约束/回转工

它说:

由于ImageRetriever类将 下载图像,并将其放置一个 大标签上,提供在构造函数中的标签和 图像URL是 方便。 ImageRetriever需要 URL来检索图像。提供 标签,以便ImageRetriever 实例可以自行设置标签的图标 。如果使用内部类,则 甚至可能不会在构造函数 中提供此 信息,因为工作线程将能够 直接访问信息。 然而,在 提供信息的构造可以帮助您的应用程序 更加线程安全的,因为这 信息不会之中 ImageRetriever实例

我对这个困惑共享。如果SwingWorker方法更新EDT中的gui组件(在JLabel链接的示例中),为什么在ImageRetriever(= SwingWorker)实例中不共享它们更为线程安全?如果我们有多个SwingWorkers并且在done()方法中它们更新了同一个组件,那么我们必须使用同步原语来进行更新?我误解了什么?不是线程限制意味着只有一个线程会执行所有操作?摇摆工不是线程化的吗?

感谢

回答

1

如果标签在父类中声明,由于某种原因一个新值分配给该变量在某些时候,那么所有的swingworkers将会看到更新。因为这可能发生在美国东部时间正在更新的东西,它可能会导致怪异的行为。

例如:

SW in EDT - label.setText(...); 
Thread1 - label = new JLabel(); 
SW in EDT - label.setIcon(...); 

如果标签变量是共享的,你会得到不一致的状态(无标签的文字或图标)。

更新 将标签存储为通过构造函数传递的变量是避免此问题的一种方法。如果您想查看更改但不在方法执行过程中,则使用方法局部变量。您可以在方法开始时指定它,以确保它不会在外部更改。

如果使用内部类和父类的属性,这将是这样的:

public void done() { 
    JLabel l = label; 
    l.setText(...); 
    l.setIcon(...); 
} 

如果变量定义为SW的属性,你必须创建一个获得某种方式存储在主类中的值(例如getter)

+0

但在您的示例中,该标签由EDT之外的线程访问,这是不允许的。如果在你的例子中,第二行缺失(Thread1 - label = new JLabel();),我们在EDT中有 SW - label.setText(...); SW在EDT - label.setText(...); 这是线程安全的。我的问题涉及Jtree,不像标签那样简单 – Cratylus 2010-09-04 20:43:44

+0

禁止在EDT之外的组件上调用方法,但允许分配变量。是的,如果组件上没有其他操作(没有Thread1),它将是线程安全的。 – Guillaume 2010-09-05 09:02:06

+0

最后一个问题。如果我在SW的构造函数中传递了jlabel,那么Thread1所做的任何更改都不会反映在SW done()方法中。对?我的意思是SW会有一个标签,并且thread1会将标签指向另一个标签,但是SW将具有旧值。我将如何确保在构造函数中传递的变量(如果已更改)在EDT中具有新的使用价值?如果,在调用SW.execute()之前,我有一个具有值“A”的字符串变量。并且在调用execute之后变量的值是“B”,那么在done()中这将如何显示? – Cratylus 2010-09-05 13:59:59