1. Hungry, static constant, available

public class Singleton { private final static Singleton INSTANCE = new Singleton(); private Singleton() { } public static Singleton getInstance() { return INSTANCE; }}Copy the code

Advantages:

  • Written in simple
  • Instantiation is done when the class is loaded

2. Hungry, static code block, available

public class Singleton { private final static Singleton INSTANCE; static { INSTANCE = new Singleton(); } private Singleton() { } public static Singleton getInstance() { return INSTANCE; }}Copy the code

3. Lazy, unsafe thread, unusable

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

Disadvantages:

  • Threads are not safe because multiple threads create instances repeatedly

4. Lazy, thread-safe, synchronous method, not recommended

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

Disadvantages:

  • Low efficiency

5. Lazy, thread unsafe, synchronized code block, not available

public class Singleton {

    private static Singleton instance;

    private Singleton() {

    }

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

6. Double check, recommended for interviews

public class Singleton {

    private volatile static Singleton instance;

    private Singleton() {

    }

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

Advantages:

  • Double judgment ensures thread safety
  • Delay loading, high efficiency

Why volatile?

New Singleton() Actually creates an object in three steps, and using volatile prevents reordering.


7. Static inner classes, recommended

public class Singleton {

    private Singleton() {

    }

    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}
Copy the code

Advantages:

  • Thread safety
  • Lazy loading

8. Enumeration, recommended (the best singleton in production practice)

Public enum Singleton {/** * INSTANCE */ INSTANCE; /** * Other methods... */ public void test(){ } }Copy the code

How are other classes used?

public static void main(String[] args) throws InterruptedException {
    Singleton.INSTANCE.test();
}
Copy the code

Different ways to write it

  • Hungry: Simple, but no lazy loading
  • Lazy: There are thread safety issues
  • Static inner classes: available
  • Double check: for an interview
  • Enumeration: best

Why is enumeration the best approach

1. Joshua Bloch clearly states in Effective Java that “enumerations have not yet been widely adopted to implement singletons, but enumerations of single elements have become the best way to implement singletons.”

2. Simple writing

3. The thread security is guaranteed

4. Avoid deserialization breaking singletons

The application of various writing methods

  • The best way to do this is to use enumerations, because it also prevents deserialization from recreating new objects;
  • Non-threaded synchronized methods cannot be used;
  • If the program starts with too many resources to load, use lazy loading.
  • The hanky-hank style is not applicable if object creation requires configuration files;
  • Lazy loading is good, but static inner classes introduce programming complexity.