[英]Java Swing EDT & Concurrency
I was just wondering if it is still necessary to ensure synchronicity in an invokeLater() Runnable. 我只是想知道是否仍然需要确保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);
}
}
});
}
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. 对于相当糟糕的示例感到抱歉,但我们必须假设
text
被不同的线程修改,无法注入,并且依赖于正确的值。
Is this the proper solution or will I unintentionally create a deadlock problem by sending synchronized code off into an unknown context..? 这是正确的解决方案,还是通过将同步代码发送到未知的上下文中而无意中造成死锁问题?
Thanks. 谢谢。
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;
}
}
}
This will ensure that if two threads try to call setText
concurrently then they will not clobber each other. 这将确保如果两个线程尝试同时调用
setText
那么它们将不会相互破坏。 The first thread in will set the value of text
and enqueue a UI update with that value. 第一个线程将设置
text
的值,并使用该值将UI更新排入队列。 The second thread will also set the value of text
and enqueue a second UI update. 第二个线程还将设置
text
的值并将第二个UI更新排入队列。
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. 最终结果是UI最终将显示最新的文本值,但内部
text
变量将立即包含最新值。
A couple of notes: 几个笔记:
TEXT_LOCK
) means you are not vulnerable to code somewhere else locking the monitor on the Whatever
instance and inadvertently causing a deadlock. TEXT_LOCK
)意味着您不会受到其他地方的代码攻击,无法将监视器锁定在Whatever
实例上,并且无意中导致死锁。 Best to always keep tight control of your lock objects. setText
method synchronized, subject to the caveat that it does make you potentially vulnerable to deadlock as above. setText
方法同步,但需要注意的是它确实使您可能容易受到上述死锁的影响。 text
also needs to be synchronized even though Strings
are immutable. Strings
是不可变的,也需要同步读取text
的值。 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. Check out Brian Goetz's Java Concurrency in Practice for a great dive into the tricky parts of concurrency (including the memory model weirdness). 查看Brian Goetz的Java Concurrency in Practice ,深入了解并发的棘手部分(包括内存模型的怪异)。
now it would be correct, all output from task must be wrapped ito InvokeLater(), another example for update GUI from BackGround task(s) is here 现在它是正确的,任务的所有输出都必须包装在InvokeLater()中,另一个来自BackGround任务的更新GUI的例子在这里
private String text;
private void updateText() {
synchronized (FrameImpl.this) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
someLabel.setText(text);
}
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.