gpt4 book ai didi

Java Swing EDT 和并发

转载 作者:搜寻专家 更新时间:2023-11-01 02:32:05 26 4
gpt4 key购买 nike

我只是想知道是否仍然有必要确保 invokeLater() Runnable 中的同步性。

我遇到了死锁,需要在保持并发的同时克服它。

这会是好的代码示例吗?:

private String text;

private void updateText()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
synchronized(FrameImpl.this)
{
someLabel.setText(text);
}
}
});
}

对于这个相当糟糕的示例,我们深表歉意,但我们必须假设 text 正在被不同的线程修改,无法注入(inject),并且依赖于正确的值。

这是正确的解决方案,还是我会通过将同步代码发送到未知上下文而无意中造成死锁问题?

谢谢。

最佳答案

更好的解决方案是这样的:

public class Whatever {
private String text;
private final Object TEXT_LOCK = new Object();

public void setText(final String newText) {
synchronized (TEXT_LOCK) {
text = newText;
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
someLabel.setText(newText);
}
});
}

public String getText() {
synchronized (TEXT_LOCK) {
return text;
}
}
}

这将确保如果两个线程尝试同时调用 setText 那么它们将不会互相干扰。第一个线程将设置 text 的值并使用该值将 UI 更新加入队列。第二个线程还将设置 text 的值并将第二个 UI 更新加入队列。

最终结果是 UI 最终将显示最新的文本值,但内部 text 变量将立即包含最新的值。

一些注意事项:

  1. 使用单独的锁定对象(即 TEXT_LOCK)意味着您不容易受到其他地方的代码将监视器锁定在 Whatever 实例上并无意中导致死锁。最好始终严格控制锁定对象。最好尽量减少同步块(synchronized block)的大小。
  2. 可以使整个 setText 方法同步,但需要注意的是,它确实会使您可能容易受到上述死锁的影响。
  3. 读取 text 的值也需要同步,即使 Strings 是不可变的。 Java 内存模型有一些微妙之处,这意味着您总是需要围绕可由多个线程读取/写入的变量进行同步。

查看 Brian Goetz 的 Java Concurrency in Practice深入研究并发的棘手部分(包括内存模型怪异)。

关于Java Swing EDT 和并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6839364/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com