Common Design Patterns-01 Single Case Design Patterns

  Singleton model: requires only one instance of a class, and provides global access methods.

1. Lazy and hungry singleton models

1.1 Slacker

    The lazy singleton pattern is instantiated by static initialization when the class is loaded.

public class Layzerbones {
    private static Layzerbones layzer = new Layzerbones();
    private Layzerbones(){}
    public static Layzerbones getInstance(){
        return layzer;
    }
}

1.2 Hungry

  Hungry singleton mode is instantiated when it is called for the first time;

public class Badmash {
    private static Badmash badmash;
    private Badmash(){}
    public static synchronized Badmash getInstance(){//方法一
        if(badmash == null){
            badmash = new Badmash();
        }
        return badmash ;
    }
    public static Badmash getInstance2(){//方法二
        if(badmash == null){
            synchronized (Badmash.class){
                if(badmash == null){
                    badmash = new Badmash();
                }
            }
        }
        return badmash ;
    }
}

What the above two singleton models have in common :

1. The current class is used as a static member variable; 2. The constructor is privatized; 3. Provide a static accessible instantiation method

The difference is:

1. Lazy style: thread safety;

2. The hungry Han style, the thread is not safe, so we must increase the lock;

3. There are two ways for hungry Chinese style locks, one is to add a lock on the method, the lock is a bytecode file of the class; the other is the synchorinize code block, and the lock can be customized

4. The purpose of double verification of synchorinize code blocks is to improve the efficiency of execution;

2. The problem and optimization of hungry Chinese double check lock

       The problem is that the existing logic code may be reordered during compilation by the compiler;

  

 

This is a drawing in "JAVA Concurrent Programming Art", which clearly illustrates the problem; as shown below;

 

 

 

The initialization order of normal objects is: 1. First allocate memory space to the object; 2. Initialize the object; 3. Point the initialized instance to the allocated memory address

But the problem is that because JMM internal reordering, initialization of objects, and the instance address points to the memory address can be reordered;

Then there will be problems: before the object has been initialized, it has already pointed to the memory address, and the object is null; when another thread accesses again, it will judge again, null, and re-initialize the object.

 

 Of course, for this kind of problem, it is better to solve it. Add a volatile modifier to the static member . This is a lightweight lock to make the modified variable atomic ;

    private volatile static Badmash badmash;

Of course, there are other ways to avoid this problem.

3. Static internal singleton design model

      In order to avoid the above problem of object initialization and rearrangement, you can use the principle of class locking in the initialization process to implement singletons through internal classes;

public class Singleton { 
    private Singleton(){
    }
      public static Singleton getInstance(){  
        return Inner.instance;  
    }  
    private static class Inner {  
        private static final Singleton instance = new Singleton();  
    }  
} 

4. Enumerate singleton pattern

     1. Set the instance enumeration INSTINCT in the enumeration ;

     2. Then initialize the object that needs to be initialized in the private constructor ;

     3. Provide external non-static methods for obtaining instances

public enum SingleEnum {
INSTINCT;
private User user ;
SingleEnum(){
user = new User();
}
public User getInstance(){
return user;
}
}

 

 

The above is the most common singleton model!

At this point, it is finished!

 

Guess you like

Origin www.cnblogs.com/perferect/p/12760832.html