java singleton mode means to ensure that there is only one instance of a class and provide the instance to the global during the whole system operation.
Main implementation mode:
1, Instant load
Class objects are created as soon as the class file is loaded, whether or not they are called. (starving Han style)
Advantages: fast access to objects, thread safety.
Disadvantages: class loading is slow, which consumes unnecessary resources of the system.
package package01_single; public class Eager { //Static private member object all objects of this class share one (single example) private static Eager instance = new Eager(); //The private constructor cannot be created directly. The class cannot be inherited private Eager(){} //Get unique instance through static method public static Eager getInstance() { return instance; } } class EagerTest { public static void main(String[] args) { //Direct class name. Method name calls static method Eager eager01 = Eager.getInstance(); Eager eager02 = Eager.getInstance(); System.out.println(eager01); System.out.println(eager02); } }
2, DCL double lock implementation
Only when the object needs to be called can the object be created (lazy type). By judging whether the object already exists to implement a single instance, a synchronous lock is added to ensure thread safety.
Advantages: both can ensure thread safety, and the single instance object initialization calls getInstance without synchronizing locks. The resource utilization rate is high.
Disadvantages: the first load is a little slow, and errors occasionally occur due to the JVM underlying model. Because the use class of private constructor cannot be inherited.
package package01_single; public class DoubleCheckLock { private static DoubleCheckLock instance = null; private DoubleCheckLock() {} /** * The first level of judgment is to avoid unnecessary synchronization * The second level of judgment is to create an instance in the case of null */ public static DoubleCheckLock getInstance() { if(instance == null) { synchronized (DoubleCheckLock.class) { if(instance == null) { instance = new DoubleCheckLock(); } } } return instance; } } class DoubleCheckLockTest { public static void main(String[] args) { //Direct class name. Method name calls static method DoubleCheckLock d1 = DoubleCheckLock.getInstance(); DoubleCheckLock d2 = DoubleCheckLock.getInstance(); System.out.println(d1); System.out.println(d2); } }
3, Static inner class implementation
It is also a delayed load. java virtual machine ensures its thread safety without lock.
Advantages: thread safety, creating objects when using, reducing resource consumption.
Disadvantage: it needs two classes to implement. Although the internal class object is not created, its class object is still created. At the same time, the class cannot be inherited.
package package01_single; public class StaticClass { private StaticClass() {} //Static inner class private static class StaticIndoor { private final static StaticClass instance = new StaticClass(); } public static StaticClass getInstance() { return StaticIndoor.instance; } } class StaticClassTest { public static void main(String[] args) { StaticClass s1 = StaticClass.getInstance(); StaticClass s2 = StaticClass.getInstance(); System.out.println(s1); System.out.println(s2); } }
4, Container implementation
Multiple singleton types are injected into a unified management container, and the singleton is guaranteed by a unique key value. This method solves the problem that classes cannot be inherited in static inner class implementation and DCL implementation. Spring-IOC uses container implementation.
package package01_single; import java.util.HashMap; import java.util.Map; public class Container { private static Map<String,Object> map = new HashMap<String, Object>(); private Container() {} public static void addInstance(String key, Object instance) { if(!map.containsKey(key)) { map.put(key,instance); } } public static Object getInstance(String key) { return map.get(key); } } class T implements Runnable { public void run() { Container.addInstance("object", new Object()); Object instance = Container.getInstance("object"); System.out.println(Thread.currentThread().getName() + " " + instance); } } class Test { public static void main(String[] args) { Thread t1 = new Thread(new T()); Thread t2 = new Thread(new T()); t1.start(); t2.start(); } }