以下是我当前代码的简化版本。我很确定我在语法方面没有做错任何事情,而且我找不到我的概念错误。
这是我尝试实现的一种观察者模式。我负担不起从 Java.utils.observable 继承,因为我的类已经很复杂并且继承自另一个类。 这里有两个部分:
有一个实现 Runnable 的 Notifier 类:
public class Notifier implements Runnable{
public void run()
{
while(true)
{
MyDataType data = getData();
if(data.isChanged()==true)
{
refresh();
}
}
}
}
然后是我的主类,它需要响应对 MyDataType 数据的更改。
public class abc {
private MyDataType data;
public void abc(){
Notifier notifier = new Notifier();
Thread thread = new Thread(notifier);
thread.start();
}
public MyDataType getData(){
return this.data;
}
public void refresh(){
MyDatatype data = getData();
//Do something with data
}
}
问题:发生的事情是通知程序在“数据”更改时调用 refresh()。但是在 refresh() 中,当我执行 getData() 时,我得到的是旧版本的“数据”! 我应该提到代码的其他部分也在调用 refresh() 函数。
- 我忽略了什么?
- 对于此问题还有其他更好的解决方案吗?
- 如果我不能开箱即用地应用默认的 Java 实现,我应该如何设计主题-观察者系统?
最佳答案
when I do getData(), I am getting the old version of 'data'!
您的 data
字段由多个线程共享,因此必须用 volatile
关键字标记。
private volatile MyDataType data;
这会导致围绕读取和写入的“内存屏障”,使值对所有线程可见。即使通知程序线程正在调用 getData()
,data
的值也会在其内存缓存中被检索出来。如果没有内存屏障,data
值将随机更新或从不更新。
正如@JB 在评论中提到的,volatile
保护您免受data
字段的重新分配。如果您更新 current data
值中的字段之一,则不会跨越内存屏障,通知程序的内存不会被更新。
回顾一下你的代码,看起来是这样的:
if(data.isChanged()==true)
{
refresh();
}
如果 data
没有被分配给一个新对象,那么将 data
设置为 volatile
将无济于事。您将必须:
- 每当
data
更新时,设置某种volatile boolean dirty;
字段。 - 每次都更新或读取
synchronize
block 中的data
。
关于java - 线程执行的频率是多少?我的观察者模式出错了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10985874/