Regardless of how you implement the singleton pattern, the core principle is to privatize the constructor and get a unique instance through static methods. This fetching process must be thread-safe and prevent serialization from causing instance objects to be regenerated.
1. LanHanShi
Adding synchronized ensures uniqueness of singleton objects in multithreaded situations.
Advantages: Singletons are instantiated only when they are used, saving resources to some extent.
Disadvantages: instantiation is required for the first load, which is slightly slower and synchronizes with each call, causing unnecessary overhead.
view plain
copy
?
- public class Singleton {
- private static Singleton instance;
- private Singleton() {
- }
- public static synchronized Singleton getInstance() {
- if (instance == null) {
- instance = new Singleton();
- }
- return instance;
- }
- }
public class Singleton { private static Singleton instance; private Singleton() { } public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }}Copy the code
2. The hungry
Instantiation occurs when the class is loaded
Advantages: No lock, thread safety, high execution efficiency
Disadvantages: Class initialization at load time, wasteful of resources
view plain
copy
?
- public class Singleton {
- private static Singleton instance = new Singleton();
- private Singleton() {
- }
- public static Singleton getInstance() {
- return instance;
- }
- }
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; }}Copy the code
view plain
copy
?
- public class Singleton {
- private static Singleton instance = null;
- static {
- instance = new Singleton();
- }
- private Singleton() {
- }
- public static Singleton getInstance() {
- return instance;
- }
- }
public class Singleton { private static Singleton instance = null; static { instance = new Singleton(); } private Singleton() { } public static Singleton getInstance() { return instance; }}Copy the code
3. Double check lock (DCL)
A further refinement of lazy not only avoids the unnecessary overhead of synchronizing every time, but also saves resources by instantiating when needed.
view plain
copy
?
- public class Singleton {
- private volatile static Singleton instance = null;
- private Singleton() {
- }
- public static Singleton getInstance() {
- if (instance == null) {
- synchronized (Singleton.class) {
- if (instance == null) {
- instance = new Singleton();
- }
- }
- }
- return instance;
- }
- }
public class Singleton {
private volatile static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}Copy the code
Instance = new Singleton() : volatile = new Singleton()
view plain
copy
?
- inst = allocat(); // Step 1: Allocate memory
- constructor(inst); // Step 2: Execute the constructor
- instance = inst; // Set the instance object to the allocated memory space.
inst = allocat(); Constructor (inst); Instance = inst; // Set the instance object to the allocated memory space.Copy the code
This is where the Java memory model comes in.
Because the Java compiler allows the processor to execute out of order, the order of the second and third steps is not guaranteed. If instance is called by another thread when the third step is completed and the second step is not executed, it will be judged as null and used directly. However, the constructor has not been executed and the member variables and other fields have not been initialized. This is the PROBLEM of DCL failure, and it is very difficult to repeat.
Write operations on volatile variables are not allowed to be out of order with previous reads and writes. Read operations on volatile variables are not allowed to be out of order with subsequent reads and writes.
When a thread wants to use a volatile variable in shared memory, it reads directly from main memory, rather than using a copy in its own local memory. When a thread writes to a volatile variable, it flushers the value of the shared variable to shared memory.
The use of volatile may affect performance somewhat, but this is a small sacrifice for the stability of the program. The above code can also be optimized:
view plain
copy
?
- public class Singleton {
- private volatile static Singleton instance = null;
- public static Singleton getInstance() {
- Singleton inst = instance; // Create temporary variables
- if (inst == null) {
- synchronized (Singleton.class) {
- inst = instance;
- if (inst == null) {
- inst = new Singleton();
- }
- }
- }
- return inst; // Returns a temporary variable
- }
- private Singleton() {}
- }
public class Singleton { private volatile static Singleton instance = null; public static Singleton getInstance() { Singleton inst = instance; Synchronized (Singleton. Class) {synchronized (Singleton. Class) {synchronized (Singleton. if (inst == null) { inst = new Singleton(); } } } return inst; Private Singleton() {}}Copy the code
We added a temporary variable so that, except for the first initialization, subsequent accesses would reduce access to instance and never improve performance to any degree.
4. The enumeration
Simple to write, thread safe
public enum Singleton {
INSTANCE;
}Copy the code
The simplicity of writing is one of the most important features of enumerations. The most important is that the default enumeration instance is created thread-safe and is in any case a singleton.
We use the singleton pattern so that instances of a class are unique. However, if the class is Serializable, such as when the Serializable interface is implemented, it is possible to write a singleton to disk by serializing it, and then get an instance in the city, effectively. Even if the constructor of a function is private, deserialization can create a new instance of the class in a special way, equivalent to calling the constructor of the class. Deserialization provides a special hook function with a private, instantiated readResolve() method that gives the developer control over deserialization of the object. To ensure that the singleton nature is preserved during deserialization, you can add a readResolve() method to the singleton
view plain
copy
?
- private Object readResolve() throws ObjectStreamException {
- return instance;
- }
private Object readResolve() throws ObjectStreamException {
return instance;
}Copy the code
The readResolve() method is called when deserialization reads the read object from the I/O stream, essentially replacing the object created in deserialization directly with the object returned from readResolve().
Resources: developer.51cto.com/art/201202/…
5. Static inner class singleton
Thread-safe, which ensures uniqueness and instantiates only when needed
view plain
copy
?
- public class Singleton {
- private Singleton() {
- }
- public static Singleton getInstance() {
- return SingletonInstance.instance;
- }
- private static class SingletonInstance {
- private static final Singleton instance = new Singleton();
- }
- }
public class Singleton { private Singleton() { } public static Singleton getInstance() { return SingletonInstance.instance; } private static class SingletonInstance { private static final Singleton instance = new Singleton(); }}Copy the code
6. The container implements the singleton pattern
view plain
copy
?
- public class Singleton {
- private static Map<String, Object> instanceMap = new HashMap<String, Object>(a);
- private Singleton() {
- }
- public static void addInstance(String key, Object instance) {
- if (! instanceMap.containsKey(key)) {
- instanceMap.put(key, instance);
- }
- }
- public static Object getInstance(String key) {
- return instanceMap.get(key);
- }
- }
public class Singleton {
private static Map<String, Object> instanceMap = new HashMap<String, Object>();
private Singleton() {
}
public static void addInstance(String key, Object instance) {
if (!instanceMap.containsKey(key)) {
instanceMap.put(key, instance);
}
}
public static Object getInstance(String key) {
return instanceMap.get(key);
}
}Copy the code
Reference connection:
Segmentfault.com/a/119000000…
www.infoq.com/cn/articles…
www.race604.com/java-double…
Mp.weixin.qq.com/s?__biz=MzA…