gpt4 book ai didi

java - 线程执行的频率是多少?我的观察者模式出错了?

转载 作者:行者123 更新时间:2023-11-29 08:06:18 24 4
gpt4 key购买 nike

以下是我当前代码的简化版本。我很确定我在语法方面没有做错任何事情,而且我找不到我的概念错误。

这是我尝试实现的一种观察者模式。我负担不起从 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/

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