Java Swing EDT &并发 [英] Java Swing EDT & Concurrency

查看:33
本文介绍了Java Swing EDT &并发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was just wondering if it is still necessary to ensure synchronicity in an invokeLater() Runnable.

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

I am encountering deadlock and need to overcome it while maintaining concurrency.

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

Would this be an example of good code?:

private String text;

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

对不起,这个例子很糟糕,但我们必须假设 text 正在被不同的线程修改,无法注入,并且依赖于正确的值.

Sorry for the rather bad example, but we must assume that text is being modified by different threads, cannot be injected, and is reliant on a correct value.

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

Is this the proper solution or will I unintentionally create a deadlock problem by sending synchronized code off into an unknown context..?

谢谢.

推荐答案

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

A better solution would be something like this:

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 更新排入队列.

This will ensure that if two threads try to call setText concurrently then they will not clobber each other. The first thread in will set the value of text and enqueue a UI update with that value. The second thread will also set the value of text and enqueue a second UI update.

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

The end result is that the UI will eventually show the most recent text value, but the internal text variable will immediately contain the most recent value.

一些注意事项:

  1. 使用单独的锁定对象(即 TEXT_LOCK)意味着您不容易受到其他地方的代码的影响,该代码将监视器锁定在 Whatever 实例上并无意中导致死锁.最好始终严格控制锁定对象.最好也尽量减少同步块的大小.
  2. 可以使整个 setText 方法同步,但需要注意的是,它确实使您可能容易受到上述死锁的影响.
  3. 读取text 的值也需要同步,即使Strings 是不可变的.Java 内存模型有一些微妙之处,这意味着您总是需要同步可以由多个线程读取/写入的变量.
  1. Using a seperate lock object (i.e. TEXT_LOCK) means you are not vulnerable to code somewhere else locking the monitor on the Whatever instance and inadvertently causing a deadlock. Best to always keep tight control of your lock objects. It's also best to minimize the size of your synchronized blocks.
  2. You could make the whole setText method synchronized, subject to the caveat that it does make you potentially vulnerable to deadlock as above.
  3. Reading the value of text also needs to be synchronized even though Strings are immutable. There are subtleties to the Java memory model that mean you always need to synchronize around variables that can be read/written by multiple threads.

查看 Brian Goetz 的Java 并发实践深入了解并发的棘手部分(包括内存模型的怪异性).

Check out Brian Goetz's Java Concurrency in Practice for a great dive into the tricky parts of concurrency (including the memory model weirdness).

这篇关于Java Swing EDT &并发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆