简体   繁体   English

在Java中清除Singleton实例

[英]Clear Singleton instance in Java

I have a Singleton class to save the state of an application's module. 我有一个Singleton类来保存应用程序模块的状态。 This class simply have a lot of class variables with setters and getters : 这个类只有很多带有setter和getter的类变量:

public class ModuleState{

private static ModuleState instance;

private A a;
private B b;
private C c;
..
..
..
..

private ModuleState (){}

public ModuleState getInstance(){
    if(instance==null)
        instance=new ModuleState();

    return instance;
}

} }

At a precise moment of the application lifecycle, i have the need to CLEAR the module's state. 在应用程序生命周期的精确时刻,我需要清除模块的状态。 What i do now is to reset ALL the variables in ModuleState by a clearAll() method like this: 我现在做的是通过clearAll()方法重置ModuleState中的所有变量,如下所示:

public void clearAll(){
    a=null;
    b=null;
    c=null;

    ..
    ..
}

My question is the following : there is a cleaner method to do this reset? 我的问题如下:有一个更简洁的方法来重置? Possibly clearing the singleton instance itself, without resetting every class variable? 可能清除单例实例本身,而不重置每个类变量?

The problem with this approach is that i may have the need to add a new class variable to the ModuleState. 这种方法的问题是我可能需要向ModuleState添加一个新的类变量。 In this case i must remember to add a line in the clearAll() method to reset the new variable. 在这种情况下,我必须记住在clearAll()方法中添加一行来重置新变量。

What about ... 关于什么 ...

public static volatile ModuleState instance = null;

public static void reset() {
    instance = new ModuleState();
}

ps : as per discussion below: in a multithreaded environment it's very important to synchronize the access on the instance because the JVM is allowed to cache its value. ps :根据下面的讨论:在多线程环境中,同步对实例的访问非常重要,因为允许JVM 缓存其值。 You can use volatile as shown above. 您可以使用volatile如上所示。 Thanks to all! 谢谢大家!

Cheers! 干杯!

no, this approach is perfectly acceptable. 不,这种方法是完全可以接受的。 you are of course synchronizing access to these state objects in some way, right? 你当然是以某种方式同步对这些状态对象的访问,对吧? otherwise you risk someone seeing a half-cleared config object. 否则你会冒一个人看到半清除配置对象的风险。

another thing you could do to future-proof yourself against any extra state added in the future is store all of your state in a HashMap, for example, instead of individual fields. 你可以做的另一件事就是将来自己对抗未来添加的任何额外状态,例如,将所有状态存储在HashMap中,而不是单个字段。 this way, clear()ing the hashmap ensures that all state is wiped and adding any extra state in the future becomes safer 这样,clear()的hashmap确保擦除所有状态,并且在将来添加任何额外状态变得更安全

You need to maintain the same object instance, in order to comply with the Singleton pattern, so your approach makes sense: altering the members. 您需要维护相同的对象实例,以符合Singleton模式,因此您的方法有意义:更改成员。

However, if you wanted to clean it up a little bit, why not just have an internal list, like: 但是,如果你想稍微清理它,为什么不只是有一个内部列表,如:

 ArrayList<Object> members = new ArrayList<Object>();
 // If it actually is Object, there's no need to paramaterize.
 // If you want, you can actually make the members implement a common interface,
 // and parameterize the ArrayList to that.

Another Option would be to have a HashMap , that binds the key word to the member. 另一个选项是拥有一个HashMap ,它将关键字绑定到成员。

 HashMap<String,Object> members = new HashMap<String,Object>();
 // Again, same parameterization rules apply.

For an ArrayList or a HashMap , the clearAll method might look like this: 对于ArrayListHashMapclearAll方法可能如下所示:

public class ModuleState()
{
    public void clearAll()
    {
          members.clear();
    }
}

This method won't need to change. 这种方法不需要改变。

Make an inner class to hold the fields, then replace that instance when you want to reset. 创建一个内部类来保存字段,然后在要重置时替换实例。 The write to the field would make the change to all three fields essentially atomic. 对字段的写入将使对所有三个字段的更改基本上是原子的。

public class ModuleState {

private static volatile ModuleState instance;

private static class Values {
    A a;
    B b;
    C c;
}
private volatile Values values = new Values()(

private ModuleState (){}

public ModuleState getInstance(){
    if (instance==null) {
        synchronized (ModuleState.class) {
            if (instance==null) {
                instance = new ModuleState();
            }
        }
    }

    return instance;
}

public synchronized A getA() {
     return values.a;
}

public synchronized void reset() {
    values = new Values();
}

By the way, your null checking initialization code was not threadsafe. 顺便说一下,你的null检查初始化代码不是线程安全的。 I fixed that too. 我也解决了这个问题。

Note that to make this work, you must make the reference to values volatile and synchronize all access to it, otherwise (due to the java memory model) other threads than the one that calls reset() may see the old reference. 请注意,要使其工作,您必须引用values volatile并同步对它的所有访问,否则(由于java内存模型)其他线程而不是调用reset()的线程可能会看到旧引用。

May be this can help you: 可能这可以帮到你:

public class SingletonBean {

    private static SingletonBean instance = new SingletonBean();
    private static Object privateMutex = new Object();

    private SingletonBean() {
        //to prevent instantiation
    }



public class ObjectsContainer {
    private Object A;
    private Object B;
    private Object C;

    public Object getA() {
        return A;
    }

    public void setA(Object a) {
        A = a;
    }

    public Object getB() {
        return B;
    }

    public void setB(Object b) {
        B = b;
    }

    public Object getC() {
        return C;
    }

    public void setC(Object c) {
        C = c;
    }
}

    private ObjectsContainer objectsContainer;

    private void resetObjectsContainer() {
        objectsContainer = new ObjectsContainer();
    }

    public static SingletonBean getInstance() {
        return SingletonBean.instance;
    }

    public static void clearAll() {
        synchronized (privateMutex) {
            SingletonBean.getInstance().resetObjectsContainer();
        }
    }

    public static ObjectsContainer getObjectsContainer() {
        synchronized (privateMutex) {
            return instance.objectsContainer;
        }
    }
}

public class SomeClass {
    public void someMethod() {
        SingletonBean.getObjectsContainer().getA();
    }
}

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

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