Study notes: singleton mode

Singleton mode: What is the singleton mode ? Dim ? When is it used ? Why use it? How to use it? ( First come with a wave of quality five consecutive )

What is it?

Singleton mode? Literally understood, single: one, example: instance, which is what we call the object

What's the use?

It is for the reuse of resources, just need to be assigned or initialized once, and everyone can reuse it

When is it used? Why use it? (Only one such as calendar, only one such as IOC container)

Listener listener, Calender calendar class, IOC container class, configuration information Config (one move is a singleton), these are all singletons

How to use it? (I can’t say a word, let me talk about it carefully)

Below I will use the hungry style, the lazy style, the most powerful singleton mode, enumeration, registration , deserialization, how to ensure the singleton and other singleton modes to explain in detail 

 

  1. Hungry Chinese style (There are obvious mistakes that make it impossible to realize the singleton, the answer is hidden in the following text)

What is Hungry Chinese Style? My understanding is that I can’t wait to eat when I’m hungry. Look at the 9th line of code below, which is declared as

private static final: indicates that the object is initialized when the class is loaded, and then static, so the object is kept until the program stops

Disadvantages: Naturally , no matter whether you use this object or not, it will initialize you when loading this class, and it will take up space until the program stops.

Advantages: Obviously, because it is initialized when the class is loaded, there is no concurrency problem when the object is created, that is, there is no thread safety problem, singleton can be guaranteed, and the efficiency is not bad, because it needs to be created when the object is created Save those few nanoseconds

Suggested application scenario: If you only need one copy of an object of a certain class and use it very frequently, you can use this mode

 

  1. Lazy man style (explicitly, the answer is in the picture below)

What is the lazy man style? My understanding is that when you understand the characteristics of lazy people, you don’t rush to prepare in advance for anything, and you need to prepare only when you need it.

We can see that the object in the lazy mode can be obtained by calling the method when needed, and can guarantee the singleton (can it be guaranteed?) Let’s continue to analyze the advantages and disadvantages.

Advantages: avoid the waste of memory, only obtain when the object is needed, and can basically guarantee the singleton when the concurrency is not high

Disadvantages: Obviously, the above mentioned that the singleton can be guaranteed when the concurrency is not high, but a certain singleton cannot be guaranteed when the concurrency is high. How to solve it, add a synchronized keyword in front of the method (if the performance requirements are not high, you can add , After all, the synchronization lock has to wait, if you don’t understand, you can learn about the synchronization lock synchronized)

  1. Since there are more or less shortcomings in the above, here is a lazy-style improved version (that is, the most powerful version of the title, please don't call me the title file...)

Advantages: Both the memory usage problem of the hungry man mode and the performance problem of synchronized (I have tested the performance, the speed of creating 200W objects is basically the same as the hungry man mode), the test code will not be posted, try it yourself

Disadvantages: welcome to leave a message

Registered simple interest

The registered singleton mode is also called the hierarchical singleton mode, which is to register each instance in a certain place and use a unique identifier to obtain the instance. There are two registered singleton i modes: one is enumerated singleton mode, and the other is container singleton mode.

1. Enumerated singleton mode

  The enumeration singleton mode is written as follows:

Copy code

public enum EnumSingleton {
    INSTANCE;
    private Object data;
    public Object getData() {
        return data;
    }
    public void setData(Object data) {
        this.data = data;
    }
    public static EnumSingleton getInstance(){
        return INSTANCE;
    }
}

Copy code

  The test code is as follows:

Copy code

    @Test
    void EnumSingletonTest(){
        EnumSingleton e1 = null;
        EnumSingleton e2 = EnumSingleton.getInstance();
        e2.setData(new Object());
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("EnumSingleton.obj");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(e2);
            oos.flush();
            oos.close();

            FileInputStream fis = new FileInputStream("EnumSingleton.obj");
            ObjectInputStream ois = new ObjectInputStream(fis);
            e1 = (EnumSingleton)ois.readObject();
            ois.close();
            System.out.println(e1.getData());
            System.out.println(e2.getData());
            System.out.println(e1.getData() == e2.getData());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Copy code

  The results are as follows:

  The enumeration type actually finds a unique enumeration object through the class name and the class object. Therefore, it is impossible for the enumeration object to be loaded multiple times by the class loader.

  So can reflection destroy the enumerated singleton pattern? The test code is as follows:

Copy code

    @Test
     void EnumSingletonTestThread() {
        try{
            Class clazz = EnumSingleton.class;
            Constructor c = clazz.getDeclaredConstructor();
            c.newInstance();
        } catch (Exception e){
            e.printStackTrace();
        }
    }

Copy code

  The results are as follows:

 An error did not find a no-argument construction method. View Enum source code His construction method has only one protected type construction method, the code is as follows:

  protected Enum(String name, int ordinal){ this.name = name; this.ordinal = ordinal; }  

  Do the following test again:

Copy code

    @Test
     void EnumSingletonTestThread() {
        try{
            Class clazz = EnumSingleton.class;
            Constructor c = clazz.getDeclaredConstructor(String.class,int.class);
            c.setAccessible(true);
            EnumSingleton enumSingleton = (EnumSingleton)c.newInstance("l-coil",666);
        } catch (Exception e){
            e.printStackTrace();
        }
    }

Copy code

   The test results are as follows:

  

  The error is already obvious, and reflection cannot be used to create an enumerated type.

  The enumerated singleton mode is also a kind of singleton mode implementation written in the Effective Java book. The special grammatical nature and reproduction of JDK enumeration also escort the enumeration quotation, making the enumeration singleton mode a more elegant implementation. 

2. Container singleton

  The container singleton is written as follows:

Copy code

public class ContainerSingleton {
    private ContainerSingleton(){}
    private static Map<String,Object> ioc = new ConcurrentHashMap<String,Object>();
    public static Object getBean(String className){
        synchronized (ioc){
            if(!ioc.containsKey(className)){
                Object obj = null;
                try{
                    obj = Class.forName(className).newInstance();
                    ioc.put(className, obj);
                }catch (Exception e){
                    e.printStackTrace();
                }
                return obj;
            } else {
              return ioc.get(className);
            }
        }
    }
}

Copy code

  The container-style singleton mode is used in a lot of cases, and it is edited and managed. It is not thread-safe.

Guess you like

Origin blog.csdn.net/My_SweetXue/article/details/111608549