2

我不清楚线程限制。在 Swing 中,所有 gui 组件都必须通过 EDT 更新。Java6 中提供了 SwingWorker 用于冗长的操作,并且在 done 方法中可以更新 gui 组件。我的理解是 done() 方法中的 gui 组件在 EDT 中更新。因此应该没有同步问题。但这里链接文本

它说:

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

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

谢谢

4

1 回答 1

1

如果标签是在父类中声明的,并且由于某种原因在某个时候为该变量分配了一个新值,那么所有的 swingworkers 都会看到更新。因为这可能会在 EDT 更新内容时发生,这可能会导致奇怪的行为。

例如:

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)

于 2010-09-04T20:26:33.693 回答