1. Singleton mode
1.1 Hungry Chinese style
public class TestSingle { public static void main(String[] args) { Single instance1 = Single.getSingleHunger(); Single instance2 = Single.getSingleHunger(); System.out.println(instance2 == instance1); System.out.println(instance2.hashCode()); System.out.println(instance1.hashCode()); } } class Single { private static final Single single = new Single(); private Single() {} public static Single getSingleHunger() { return single; } }
Advantages and disadvantages:
thread safety
It will be created when the class is loaded. Lazy loading is not implemented, which may waste resources.
1.2 The Lazy Man
public class TestSingle { public static void main(String[] args) { Single instance1 = Single.getSingle(); Single instance2 = Single.getSingle(); System.out.println(instance2 == instance1); System.out.println(instance2.hashCode()); System.out.println(instance1.hashCode()); } } class Single { private static Single single; private Single() {} public static Single getSingle() { if (single == null) { single = new Single(); } return single; } }
Advantages and disadvantages:
It has the effect of lazy loading, but it can only be used in single-threaded mode. All locks should be used, and double verification should be used to improve efficiency.
1.3 Two-factor authentication
public class TestSingle { public static void main(String[] args) { Single instance1 = Single.getSingle(); Single instance2 = Single.getSingle(); System.out.println(instance2 == instance1); System.out.println(instance2.hashCode()); System.out.println(instance1.hashCode()); } } class Single { private static Single single; private Single() {} public static Single getSingle() { if (single == null) { synchronized (Single.class) { if (single == null) { single = new Single(); } } } return single; } }
Advantages and disadvantages:
- The instantiation code executes only one subsequent re-access, and directly return s the instance object
- Thread safety, lazy loading, high efficiency
1.4 Static inner classes
// test function public class TestSingle { public static void main(String[] args) { Single instance1 = Single.getInstance(); Single instance2 = Single.getInstance(); System.out.println(instance2 == instance1); System.out.println(instance2.hashCode()); System.out.println(instance1.hashCode()); } } // singleton pattern class Single { // private constructor private Single(){} // Static inner class, when the Single class is called, the static inner class will not be loaded, // Only when the getInstance function is called, the static inner class will be loaded, and only once (lazy loading) // And it is thread-safe when the class is loaded, so the method is thread-safe, private static class SingleInstance { private static Single INSTANCE = new Single(); } // Provide a static public method public static Single getInstance() { return SingleInstance.INSTANCE; } }
Advantages and disadvantages:
- The class loading mechanism is adopted to ensure that there is only one thread when the instance is initialized
- The static inner class will not be instantiated immediately when the class is loaded, but when it needs to be instantiated, the SingleInstance static class will be loaded by calling the getInstance method, thereby completing the instantiation of the Single;
- The static properties of the class are only initialized when the class is loaded for the first time, so it is thread-safe
1.5 Enumeration
public class TestSingle { public static void main(String[] args) { Single instance1 = Single.INSTANCE; Single instance2 = Single.INSTANCE; System.out.println(instance2 == instance1); System.out.println(instance2.hashCode()); System.out.println(instance1.hashCode()); } } enum Single { INSTANCE; public void sayOK() { System.out.println("ok"); } }
Advantages and disadvantages:
Implementing the singleton pattern with enumeration not only avoids thread insecurity, but also avoids recreating new objects through deserialization
Singleton Pattern Summary
- The singleton mode ensures that there is only one object in the system, saving system resources. For some objects that need to be created and destroyed frequently, using the singleton mode can improve system performance
- When instantiating a singleton class, use the corresponding method to get the object instead of using new
- Singleton mode usage scenarios: Objects that need to be created and destroyed frequently, time-consuming or resource-consuming (heavyweight objects), but frequently used objects, tool objects, frequently accessed databases or File objects (such as data sources, session factories, etc.)