Definition and application scenario
Singleton mode refers to ensuring that a class has only one instance and provides a global access point. The singleton pattern is a creation pattern. The application scenarios are as follows:
- Connection pool
- applicationContext in spring
Several ways of writing singleton mode
Hungry Han style single case
Hungry Han singleton mode is initialized when the class is loaded and creates a singleton object. It is thread safe because it has been initialized when the class is loaded and cannot appear before the thread appears
//Hungry Han style public class HungrySingleton{ private static final HungrySingleton lan=new HungrySingleton(); private HungrySingleton (){} //Global access point public static HungrySingleton getInstance(){ return lan; } }
Disadvantages: initializing the object when the class is loaded may cause a waste of memory.
Static inner class singleton
Static internal classes can solve the memory waste caused by the above lazy type, which can ensure lazy loading and thread safety.
public class StaticInnerClassSingleton{ private static class SingletonHolder{ private static final StaticInnerClassSingleton INSTANCE=new StaticInnerClassSingleton(); } private StaticInnerClassSingleton(){ //Single case of preventing reflection damage if(SingletonHolder.INSTANCE!=null){ throw new RuntimeException("Multiple singletons are not allowed"); } } //Global access point public static final StaticInnerClassSingleton getInstance(){ return SingletonHolder.INSTANCE; } }
Lazy single case
The lazy singleton is lazy as its name. It will be initialized only when it is used. Let's see the simple implementation below
//Lazy single case public class LazySingleton(){ private static LazySingleton lazy=null; private LazySingleton (){} public static LazySingleton getInstance(){ //Two threads entering this method may cause thread insecurity if(lazy==null){ lazy=new LazySingleton(); } return lazy; } }
Disadvantages: in the case of multithreading, two threads may enter the if method at the same time. Both threads enter the if judgment successively and return the value successively.
Double check lock
When there is a lazy singleton with unsafe thread, some people will say that adding synchronized keywords to class methods will lead to a large range of locks and low efficiency, so there is a double check lock. The simple implementation is as follows:
public class DouSingleton{ private static DouSingleton singleton; private DouSingleton(){} public static DouSingleton getInstance(){ if(singleton==null){ synchronized(DouSingleton.class){ if(singleton==null){ singleton=new DouSingleton (); } } } return singleton; } }
Disadvantages: it may cause null pointer exceptions. The solution is to add volatile keyword to the singleton object. If you are not clear, please search for knowledge about java memory model. Here is a brief explanation. Creating objects is divided into three steps: A. opening up space; b. Initialization object information; c. Returns the address of the object to the reference. Volatile is to prevent reordering of these three steps. Thread 1 executes step ab, and thread 2 determines that the object = = null is false, which directly returns the object, resulting in the object being empty.
Singleton and serialization
public class Singleton implements Serializable{ private static Singleton singleton; private Singleton(){} public static Singleton getInstance(){ if(singleton==null){ synchronized(Singleton.class){ if(singleton==null){ singleton=new Singleton (); } } } return singleton; } //Just override this method. private Object readResolve(){ return singleton; } }
Enumerative singleton
This method is advocated by the author of Effective Java. It can avoid the problem of multi-threaded synchronization and prevent deserialization and re creation of new objects.
public enum EnumSingleton{ INSTANCE; EnumSingleton(){} public static EnumSingleton getInstance(){ return INSTANCE; } }