The singleton pattern is a creative design pattern that guarantees a single instance of a class and provides a global access point to it.

In a system where a class is often used in different places, the singleton pattern saves system resources by avoiding creating multiple instances multiple times.

The singleton pattern tends to have three characteristics: a class can only have one instance, it must provide its own creation of the instance, and it must provide methods to expose the instance.

The hungry way

Hungry people eat all at once, so this approach always creates all objects when the system is initialized, regardless of when they will be used.

Private static final SingleTon instance = new SingleTon(); private static final SingleTon instance = new SingleTon(); Public SingleTon getInstance(){return this.instance; }}Copy the code

The hunchman implementation of the singleton pattern is extremely simple, but the disadvantage is obvious. Even if the class is not used for a while, the heap must be initialized at compile time to create the internal instance.

Lazy way

Lazy people are lazy and only instantiate a unique instance of a class when the system uses it.

public class SingleTon { private static SingleTon instance= null; private SingleTon(){} public static SingleTon getInstance(){ if(null == instance){ instance = new SingleTon(); } return instance; }}Copy the code

Instance is not initialized when the class is compiled, and instance is instantiated only when the getInstance method is called.

Looks pretty!

In A multi-threaded environment, thread A and thread B simultaneously judge instance==null and instantiate instance, resulting in instance being instantiated twice. An unreferenced object is generated in the heap. In the case of large concurrency, more useless objects will be created and GC may even be triggered in advance.

Lazy mode optimization 1 (add local lock)

Thread is not safe, I believe you will first think of lock control, that you do not add so?

public class SingleTonLock { private static SingleTonLock instance= null; public SingleTonLock(){} public synchronized SingleTonLock getInstance(){ if (instance == null){ instance = new SingleTonLock(); } return instance; }}Copy the code

This method directly locks the getInstance method, which obviously results in a large number of invalid lock waits.

public class SingleTonLock { private static volatile SingleTonLock instance= null; public SingleTonLock(){} public SingleTonLock getInstance(){ if (instance == null){ synchronized(this){ If (instance == null){instance = new SingleTonLock(); } } } return instance; }}Copy the code

Volatile is used to prevent JVM instructions from being reordered, ensuring that the instance is uniquely instantiated by rechecking.

This is a good example of slacker and I recommend it, but I recommend the next one.

Lazy way optimization 2 (Enumeration class)

I think it’s best practice to implement the lazy singleton pattern using enumerated classes, which are essentially implemented with static fields, such as:

public enum Color {
    RED(), GREEN(), BLUE(), YELLOW();
}
Copy the code

Javap decompiles this enumerated class to get:

public final class com.example.test.lazy.Color extends java.lang.Enum<com.example.test.lazy.Color> { public static final  com.example.test.lazy.Color RED; public static final com.example.test.lazy.Color GREEN; public static final com.example.test.lazy.Color BLUE; public static final com.example.test.lazy.Color YELLOW; public static com.example.test.lazy.Color[] values(); public static com.example.test.lazy.Color valueOf(java.lang.String); static {}; }Copy the code

So, enumeration how to implement the singleton pattern, the above code:

public class SingleTonE { public static SingleTonE getInstance(){ return SingleTonEnum.SINGLETON.getInstance(); } private enum SingleTonEnum{ SINGLETON; private SingleTonE instance; SingleTonEnum(){ instance = new SingleTonE(); } public SingleTonE getInstance(){ return this.instance; }}}Copy the code

The enumeration class is loaded only when the getInstance method is called to get the instance, and then, as described above, generates a static field and initializes its internal singleton instance. Since the JVM guarantees that only one thread can load the class, the whole process seems very simple.

In my opinion, the singleton pattern implemented by enumerated classes is a best practice that I recommend you apply to your own projects.

In the near future, we will compile a series of design patterns, which will talk about 23 design patterns. If you are interested, please follow them


Concern the public not to get lost: there is poetry and wine and code.

Public number reply “1024” add the author wechat together to discuss learning!

The public account replies “interview questions” to send you a copy of interview questions and the author’s answers

All the case code materials used in each article are uploaded to my personal Github

Github.com/SingleYam/o…
Welcome to step on it!