Java Swing EDT 和 Java Swing并发性
我只是想知道是否仍然有必要确保 invokeLater() Runnable 的同步性。
我遇到了死锁,需要在保持并发性的同时克服它。
这是一个好的代码示例吗?:
private String text;
private void updateText()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
synchronized(FrameImpl.this)
{
someLabel.setText(text);
}
}
});
}
对于这个相当糟糕的示例感到抱歉,但我们必须假设 text
正在被不同的线程修改,无法注入,并且依赖于正确的值。
这是正确的解决方案吗?还是我会通过将同步代码发送到未知的上下文中而无意中造成死锁问题?
谢谢。
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);
}
}
});
}
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..?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
更好的解决方案是这样的:
这将确保如果两个线程尝试同时调用 setText,那么它们不会互相干扰。第一个线程将设置
text
的值,并使用该值将 UI 更新排入队列。第二个线程还将设置text
的值并将第二个 UI 更新排入队列。最终结果是 UI 最终将显示最新的文本值,但内部
text
变量将立即包含最新的值。一些注意事项:
TEXT_LOCK
)意味着您不会受到其他地方的代码的影响,将监视器锁定在Whatever
实例上并无意中导致死锁。最好始终严格控制您的锁定对象。最好还是最小化同步块的大小。setText
方法同步,但需要注意的是,它确实使您可能容易陷入上述死锁。Strings
是不可变的,读取text
的值也需要同步。 Java 内存模型有一些微妙之处,这意味着您总是需要同步可由多个线程读取/写入的变量。查看 Brian Goetz 的 Java 并发实践,深入了解其中的棘手部分并发性(包括奇怪的内存模型)。
A better solution would be something like this:
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 oftext
and enqueue a UI update with that value. The second thread will also set the value oftext
and enqueue a second UI update.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.A couple of notes:
TEXT_LOCK
) means you are not vulnerable to code somewhere else locking the monitor on theWhatever
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.setText
method synchronized, subject to the caveat that it does make you potentially vulnerable to deadlock as above.text
also needs to be synchronized even thoughStrings
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.Check out Brian Goetz's Java Concurrency in Practice for a great dive into the tricky parts of concurrency (including the memory model weirdness).
现在这是正确的,任务的所有输出都必须包装到 InvokeLater() 中,从 BackGround 任务更新 GUI 的另一个示例是 此处
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