简体   繁体   English

如果必须将 setter 值写入文件,如何确保数据一致性?

[英]How can I ensure data consistency if a setter value must be written into a file?

I am using Preferences to store application settings.我正在使用Preferences来存储应用程序设置。 My java class reads the settings at program start and then the data is available with simple getters for other classes.我的 java class 在程序启动时读取设置,然后可以通过其他类的简单 getter 获得数据。

Now I also want to implement setters because the user can change some Preferences in the program and therefore calling a setter from another java class is an easy method to change the preferences.现在我还想实现设置器,因为用户可以更改程序中的一些首选项,因此从另一个 java class 调用设置器是更改首选项的简单方法。

If I change a value in my Preferences, how can I ensure, that the data in the Preferences and in the class are consistent?如果我更改我的首选项中的值,我如何确保首选项和 class 中的数据一致? Should I just store the data within the setter in the runtime object and in the Preferences?我应该将数据存储在运行时 object 和首选项中的设置器中吗?

And most importantly: How can I ensure, that no getter is called, before the data is written into the preferences?最重要的是:如何确保在将数据写入首选项之前不调用 getter? How do I need to synchronize them?我需要如何同步它们?

Here is just a really simple example to display the issue:这只是一个显示问题的非常简单的示例:

private static final Preferences PREFERENCES = //here are valid preferences
private static final String KEY = //Some path to the attribute

private static PrefManager prefManager = new PrefManager();

private String serverIP;

private PrefManager() {
    this.serverIP = PREFERENCES.get(KEY, "");
}


public static void setServerIP(String serverIP) {
    // How do I synchronize the PREFERENCE object and this setter to prevent getter
    // calls between put and = call here?
    PREFERENCES.put(KEY, serverIP);
    prefManager.serverIP = serverIP;
}

In terms of solving your race condition, you can create your own Preferences extension and add synchronized to set and get.在解决您的竞争条件方面,您可以创建自己的 Preferences 扩展并添加synchronized到 set 和 get。 There are two ways to create a preference extension: use a map internally and copy all key - values there, or create a facade.有两种方法可以创建首选项扩展:在内部使用 map 并在那里复制所有键值,或者创建外观。

In terms of how do you keep your application consistent: The answer to this is the Controller piece of MVC关于如何保持应用程序的一致性:答案是 MVC 的 Controller

Example of facade立面示例

I've copied all of the methods from Preferences and added them here.我已经从 Preferences 中复制了所有方法并将它们添加到这里。 You can see that the constructor takes a Preferences parameter, which is going to be the reference implementing all methods in this facade (see the first two methods absolutePath() and addNodeChangeListener(...) for examples of how this should be implemented) Also note that the methods put and get have been synchronized.您可以看到构造函数带有一个 Preferences 参数,该参数将作为实现此外观中所有方法的引用(有关如何实现的示例,请参见前两个方法 absolutePath() 和 addNodeChangeListener(...))请注意, putget方法已同步。 So if any thread is calling put, any other thread calling get will wait until put is done.因此,如果任何线程正在调用 put,则任何其他调用 get 的线程都将等到 put 完成。 (You may want to add synchronized to other methods as well) (您可能还想将同步添加到其他方法)

=================== ====================

public class MyPrefsFacade extends Preferences {
    private Preferences p;

    public MyPrefsFacade(Preferences prefs) {
      p = prefs;
    }

    public String   absolutePath() { return p.absolutePath(); }
    public void addNodeChangeListener(NodeChangeListener ncl) { p.addNodeChangeListener(ncl); }
    public void addPreferenceChangeListener(PreferenceChangeListener pcl)
    public String[] childrenNames()
    public void clear()
    public void exportNode(OutputStream os)
    public void exportSubtree(OutputStream os)
    public void flush()
    public synchronized String  get(String key, String def)
    public boolean  getBoolean(String key, boolean def)
    public byte[]   getByteArray(String key, byte[] def)
    public double   getDouble(String key, double def)
    public float    getFloat(String key, float def)
    public int  getInt(String key, int def)
    public long getLong(String key, long def)
    public boolean  isUserNode()
    public String[] keys()
    public String   name()
    public Preferences  node(String pathName)
    public boolean  nodeExists(String pathName)
    public Preferences  parent()
    public synchronized void    put(String key, String value)
    public void putBoolean(String key, boolean value)
    public void putByteArray(String key, byte[] value)
    public void putDouble(String key, double value)
    public void putFloat(String key, float value)
    public void putInt(String key, int value)
    public void putLong(String key, long value)
    public void remove(String key)
    public void removeNode()
    public void removeNodeChangeListener(NodeChangeListener ncl)
    public void sync()
    public String   toString()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM