Single case pattern: is a commonly used software design pattern that contains a special class called a singleton in its core structure. A class has only one instance, that is, a class has only one object instance.
For some classes in the system, only one instance is important. For example, there can be multiple printing tasks in a system, but there can only be one working task; when selling tickets, there are a total of 100 For one ticket, multiple windows can sell tickets at the same time, but it needs to be ensured not to overbook (the remaining number of tickets here is a single instance, and ticket sales involve multi-threading). If a mechanism is not used to uniqueize the window object, multiple windows will pop up. If these windows all display the same content, repeated creation will waste resources.
Application Scenario(Source: "Dahua Design Pattern"):
Requirement: Create a toolbox window on the front end. The toolbox will either not appear or only one will appear.
Encountered a problem: The "Toolbox" window will be created repeatedly every time you click on the menu.
Solution 1: Use the if statement to first determine whether it is null every time you create an object. If it is null, create the object again.
Requirements: If you need to instantiate the toolbox form in 5 places
Problem encountered: This small bug needs to be modified in 5 places, and the code is repeated, and the code utilization rate is low
Solution 2: Use the singleton pattern to ensure that a class has only one instance and provide a global access point to access it.
The singleton mode can be divided into the lazy style and the hungry style:
The lazy style singleton mode: does not initialize when the class is loaded.
Hungry-style singleton mode: Initialization is completed when the class is loaded, so the class loading is slow, but the object acquisition speed is fast.
The first type (lazy man, thread unsafe):
public class SingletonDemo1 {private static SingletonDemo1 instance;private SingletonDemo1(){}public static SingletonDemo1 getInstance(){if (instance == null) { instance = new SingletonDemo1(); }return instance; } }
This way of writing lazy loading is obvious. But the fatal thing is that it cannot work properly in multi-threading.
The second type (lazy guy, thread-safe):
public class SingletonDemo2 {private static SingletonDemo2 instance;private SingletonDemo2(){}public static synchronized SingletonDemo2 getInstance(){if (instance == null) { instance = new SingletonDemo2(); }return instance; } }
This way of writing is in the getInstance() method Added synchronized lock. It works well in multiple threads, and it seems to have good lazy loading, but it is very inefficient (because of locks) and does not require synchronization in most cases.
The third type (hungry man):
public class SingletonDemo3 {private static SingletonDemo3 instance = new SingletonDemo3();private SingletonDemo3(){}public static SingletonDemo3 getInstance(){return instance; } }
This method avoids multi-threading based on the classloder mechanism Synchronization problem, however, instance is instantiated when the class is loaded. At this time, initializing the instance obviously does not achieve the effect of lazy loading.
The fourth type (hunger汉, variant):
public class SingletonDemo4 {private static SingletonDemo4 instance = null;static{ instance = new SingletonDemo4(); }private SingletonDemo4(){}public static SingletonDemo4 getInstance(){return instance; } }
On the surface It seems quite different. In fact, the third method is almost the same. They are all instantiated during class initialization. Instance
The fifth method (static internal class):
public class SingletonDemo5 {private static class SingletonHolder{private static final SingletonDemo5 instance = new SingletonDemo5(); }private SingletonDemo5(){}public static final SingletonDemo5 getInsatance(){return SingletonHolder.instance; } }
This method also uses the classloder mechanism to ensure that there is only one thread when initializing the instance. It is different from the third and fourth methods in that ( Very subtle difference): The third and fourth methods are that as long as the Singleton class is loaded, the instance will be instantiated (the lazy loading effect is not achieved), and this method is that the Singleton class is loaded, and the instance is not Must be initialized. Because the SingletonHolder class is not actively used, the SingletonHolder class will only be explicitly loaded by calling the getInstance method to instantiate the instance. Imagine if instantiating an instance consumes resources and I want it to be loaded lazily. On the other hand, I don't want to instantiate it when the Singleton class is loaded, because I cannot ensure that the Singleton class may be actively used in other places. is loaded, then it is obviously inappropriate to instantiate instance at this time. At this time, this method seems more reasonable than the third and fourth methods.
Sixth (enumeration):
public enum SingletonDemo6 { instance;public void whateverMethod(){ } }
This method is advocated by Effective Java author Josh Bloch method, it can not only avoid multi-thread synchronization problems, but also prevent deserialization from re-creating new objects. It can be said to be a very strong barrier. However, I personally think that since the enum feature was only added in 1.5, writing in this way is unavoidable. It feels unfamiliar, and in actual work, I rarely see anyone writing like this.
Seventh type (double verification lock):
public class SingletonDemo7 {private volatile static SingletonDemo7 singletonDemo7;private SingletonDemo7(){}public static SingletonDemo7 getSingletonDemo7(){if (singletonDemo7 == null) {synchronized (SingletonDemo7.class) {if (singletonDemo7 == null) { singletonDemo7 = new SingletonDemo7(); } } }return singletonDemo7; } }
This is an upgraded version of the second method, commonly known as double-check locking. For detailed introduction, please see:
After JDK1.5, double-check locking can achieve the singleton effect normally.
Single instance in multi-threading In a multi-threaded program, if multiple threads access the single instance at the same time, it is possible to create multiple instances. At this time, you need to lock it with a "lock". Including locks, deadlocks, and communication between locks. This part about multi-threading will be explained in detail later!
refer to:
The above is the detailed content of Singleton mode sharing. For more information, please follow other related articles on the PHP Chinese website!