线程限制/swingworkers

Posted

技术标签:

【中文标题】线程限制/swingworkers【英文标题】:Thread-confinement/swingworkers 【发布时间】:2010-09-04 20:00:55 【问题描述】:

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

上面写着:

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

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

谢谢

【问题讨论】:

【参考方案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)

【讨论】:

但在您的示例中,标签由 EDT 之外的线程访问,这是不允许的。如果在您的示例中,缺少第二行 (Thread1 - label = new JLabel(); ) 并且我们在 EDT 中有 SW - label.setText(...); EDT 中的 SW - label.setText(...);这是线程安全的吗?我的问题涉及 Jtree,而不是标签那么简单 禁止在 EDT 之外的组件上调用方法,但允许分配变量。是的,如果没有对组件进行其他操作(没有 Thread1),它将是线程安全的。 最后一个问题。如果我在 SW 的构造函数中传递 jlabel,那么 Thread1 所做的任何更改都不会反映在 SW done() 方法中。对?我的意思是 SW 将有一个标签的引用,而 thread1 将使标签指向另一个标签,但 SW 将具有旧值。我将如何确保在构造函数中传递的变量(如果更改)在 EDT 中我们具有要使用的新值?如果,在调用 SW.execute(); 之前,我有一个值为“A”的字符串变量;并且在调用执行后变量的值为“B”,这将如何在 done() 中可见? 为什么允许赋值?我会认为那是非线程安全的?

以上是关于线程限制/swingworkers的主要内容,如果未能解决你的问题,请参考以下文章

自动验证一些线程限制? (C#)

Java多线程编程之限制优先级

提升线程:是不是可以在移动到另一个线程之前限制线程的运行时间

如何将 Tokio 线程池限制为一定数量的本机线程?

线程,限制的异步操作

JMeter 线程用户限制 - 并发执行 5000 个线程