1. Hungry Han Style (Static Constant) [Available]
public class Singleton { private final static Singleton INSTANCE = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return INSTANCE; } }
Advantage: This is a simpler way to write, that is, to instantiate a class when it is loaded.Thread synchronization issues are avoided.
Disadvantages: Instantiation is done when the class is loaded, which does not have the effect of Lazy Loading.If you have never used this instance from start to finish, it will cause a waste of memory.
2. Hungry Han Style (Static Code Block) [Available]
public class Singleton { private static Singleton instance; static { instance = new Singleton(); } private Singleton() {} public static Singleton getInstance() { return instance; } }
This is similar to the above except that the process of instantiating a class is placed in a static block of code, and when the class is loaded, the code in the static block of code is executed to initialize an instance of the class.The advantages and disadvantages are the same as above.
3. Lazy (thread insecure) [not available]
public class Singleton { private static Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; } }
This has the effect of Lazy Loading, but can only be used under a single thread.If, under multithreading, one thread enters the if (singleton == null) judgment block and has not yet had time to execute down, and another thread passes the judgment, multiple instances will be generated.This is not possible in a multi-threaded environment.
4. Lazy (thread-safe, synchronization method) [not recommended]
public class Singleton { private static Singleton singleton; private Singleton() {} public static synchronized Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; } }
To solve the thread insecurity of the third implementation above, just do a thread synchronization, and the getInstance() method is used for thread synchronization.
Disadvantage: Too inefficient, each thread synchronizes the getInstance() method when it wants to get an instance of a class.In fact, it's enough to execute the instantiation code only once. To get such an instance later, simply return it.Method synchronization efficiency is too low to be improved.
5. Lazy (Thread Safe, Synchronize Code Blocks) [Not Available]
public class Singleton { private static Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { singleton = new Singleton(); } } return singleton; } }
Because the fourth implementation is too inefficient to synchronize, it abandons the synchronization method and synchronizes to produce instantiated blocks of code.However, this synchronization does not work as thread synchronization.Consistent with the third implementation, if a thread enters an if (singleton == null) judgment block and has not yet had time to execute down, and another thread passes the judgment, multiple instances will be generated.
6. Double Check [Recommended]
public class Singleton { private static volatile Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
The Double-Check concept is not unfamiliar to multithreaded developers, as shown in the code, where we performed two if (singleton == null) checks to ensure thread safety.This way, the instantiation code is executed only once, and when accessed again later, if (singleton == null), the instantiated object is return ed directly.
Advantages: thread-safe; delayed loading; high efficiency
7. Static Internal Class [Recommended]
public class Singleton { private Singleton() {} private static class SingletonInstance { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonInstance.INSTANCE; } }
This way is similar to but different from the Hungry-Han way.Both employ a class loading mechanism to ensure that there is only one thread initializing the instance.The different place in the Hungry-Han style is that as long as the Singleton class is loaded it will be instantiated without the effect of Lazy-Loading, while the static internal class method will not be instantiated immediately when the Singleton class is loaded. Instead, when instantiation is required, the getInstance method will be called to load the Singleton Instance class, thus completing the Singleton Instance class.Instantiation of on.
The static properties of a class are only initialized when it is first loaded, so here, the JVM helps us keep threads safe, and no other threads can enter when the class is initialized.
Advantages: Avoid thread insecurity, delay loading, and high efficiency.
8. Enumeration [Recommended]
public enum Singleton { INSTANCE; public void whateverMethod() { } }
Use the enumeration added in JDK1.5 to implement the singleton mode.Not only does it avoid the problem of multithreaded synchronization, it also prevents deserialization from re-creating new objects.This is probably because enumerations were added in JDK1.5, so few people have written about them in actual project development.
Advantages: There is only one object in the system memory, which saves system resources. For some objects that need to be destroyed frequently, the use of singleton mode can improve system performance.
Disadvantages: When you want to instantiate a single class, you must remember to use the appropriate method of getting objects instead of using new, which can be confusing for other developers, especially when the source code is not visible.
Applicable occasions
Objects that need to be created and destroyed frequently;
Objects that take too much time or resources to create but are often used;
Tool class object;
Objects that frequently access databases or files.