LanHanShi

Instantiate when called

PHP implementation (lazy only)

/ / PHP singleton
class Single
{
    private static $instance = null;

    private function __construct()
    {}private function __clone()
    {
        // TODO: Implement __clone() method.
    }

    public static function getInstance()
    {
        if (!self: :$instance instanceof Single) {
            self: :$instance = new Single();
        }
        return self: :$instance; }}Copy the code

JAVA implementation

Case 1:/** * The lazy singleton instantiates itself on the first call */
public class Singleton1 {
    //1. Make the constructor private
    private Singleton1(a) {}//2. Then declare a static variable to hold a reference to the singleton
    private static Singleton1 singleton1 = null;

    //3. Obtain a reference to the singleton by providing a static method
    public static Singleton1 getInstance(a) {  
        if (singleton1 == null) {
            singleton1 = new Singleton1();
        }
        returnsingleton1; }}// Disadvantages: 1. Not useful in the face of reflection, because the Java reflection mechanism is capable of instantiating classes with private constructors. Thread unsafe because thread access is random and multiple Singleton1 instances can occur in a concurrent environment.
Copy the code
Situation 2:/** * Lazy singleton * thread safety */
public class Singleton2 {
    //1. Make the constructor private
    private Singleton2(a) {}//2. Then declare a static variable to hold a reference to the singleton
    private static Singleton2 singleton2 = null;

    //3. Obtain a reference to the singleton by providing a static method
    // Synchronized to ensure proper access in a multi-threaded environment
    public static synchronized Singleton2 getInstance(a) {
        if (singleton2 == null) {
            singleton2 = new Singleton2();
        }
        returnsingleton2; }}// Disadvantages: the method call is synchronized, which is thread safe, but it is synchronized every time. After all, 99% does not need to be synchronized
Copy the code
Case 3:/** * Lazy singletons * double lock checking * is mainly to solve thread safety issues */
public class Singleton3 {
    //1. Make the constructor private
    private Singleton3(a) {}//2. Then declare a static variable to hold a reference to the singleton
    private static Singleton3 singleton3 = null;

    //3. Obtain a reference to the singleton by providing a static method
    // To ensure an alternative implementation in a multi-threaded environment, double lock check
    public static Singleton3 getInstance(a) {
        if (singleton3 == null) {
            // This classLoader can only be loaded once
            synchronized (Singleton3.class) {
                if (singleton3 == null) {
                    singleton3 = newSingleton3(); }}}returnsingleton3; }}// Disadvantages: Null checks are made twice in getInstance to ensure that synchronization is only done the first time the singleton is called. This is also thread-safe and avoids the performance cost of synchronizing each time. But it slows down the program response speed and performance, mainly because of double locking.
Copy the code
Situation 4:/** * Lazy singleton * static inner class */
public class Singleton4 {
    //1. Make the constructor private
    private Singleton4(a) {}//2, declare a static inner class
    // The initialization of the inner class depends on the main class. The inner class instantiates only after the main class is instantiated
    private static class LazyHolder {
        // Final is added to prevent the property from being overwritten internally
        private static final Singleton4 INSTANCE = new Singleton4();
    }

    //3, provide a static method to get the instance
    // Final is added here to prevent subclasses from overriding the superclass
    public static final Singleton4 getInstance(a) {
        returnLazyHolder.INSTANCE; }}// This means that the Singleton4 class is loaded, and instance is not necessarily initialized. Because the LazyHolder class is not actively used, it is only shown to load the LazyHolder class by calling the getInstance method, thus instantiating the instance.
On the other hand, I don't want to instantiate the Singleton4 class when it is loaded, because I can't be sure that the Singleton4 class might be actively used elsewhere to get loaded. It is not appropriate to instantiate instance at this time.
// This is the best way to use the classLoader mechanism to ensure that instance is initialized with only one thread, so it is thread safe and there is no performance cost.
Copy the code

The hungry type

So we instantiate it, we instantiate it when we call it

/** * Hungrier singletons * instantiate themselves */ during class initialization
public class Singleton5 {
    //1. Make the default constructor private
    private Singleton5(a) {}//2. Declare static variables, initialize them before class instantiation, and save object references
    private static final Singleton5 singleton5 = new Singleton5();

    //3, open the static method to get the instance
    public static Singleton5 getInstance(a) {
        returnsingleton5; }}// Cons: If the class is never used, it is a waste of resources.
Copy the code

Registration form

The SpringIoc container is a registered singleton. If there is a container that contains all instances, it will be checked before the instance is generated. If there is a container, it will be removed directly.

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/** * register singletons * like Spring, register the class name and get */ from it
public class Singleton7 {
    // The bottom layer of Spring container is a map, and the IOC container is a map
    private static Map<String, Singleton7> map = new ConcurrentHashMap<String, Singleton7>();

    // Each class corresponds to a map key, which is a unique ID
    static {
        Singleton7 singleton7 = new Singleton7();
        map.put(singleton7.getClass().getName(), singleton7);
    }

    // Protect the default constructor
    protected Singleton7(a) {}// Static factory method that returns a unique instance of this class
    public static Singleton7 getInstance(String name) {
        if (name == null) {
            name = Singleton7.class.getName();
        }
        if (map.get(name) == null) {
            try {
                map.put(name, (Singleton7) Class.forName(name).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch(ClassNotFoundException e) { e.printStackTrace(); }}returnmap.get(name); }}// Registered singletons maintain instances of a singleton class and store them in a Map. Registered instances are returned from the Map, and unregistered instances are registered and returned.
// The internal implementation of a registered singleton is actually a hanney, because the static method block is instantiated when the class is loaded.
Copy the code

Enumerative singleton

/** * Enumeration singleton */
public enum Singleton6 {
    INSTANCE;

    public void getInstance(a) {}}// This approach not only solves multi-thread synchronization problems, but also prevents deserialization from creating new objects. However, it is not commonly used because the enum feature was introduced in JDK1.5
Copy the code

The difference between hungry and lazy

1, thread safety: Hunhun-style is born to be thread safe, can be directly used for multithreading without problems, lazy itself is not thread safe, in order to achieve thread safety, there are several methods above. 2. Resource loading and performance: If you instantiate a static object at the same time as the class is created, whether or not the singleton will be used later, it will take up a certain amount of memory and will be faster the first time you call it because the resource has already been initialized. Lazy loads lazily, instantiates the singleton the first time you use it, initializes the singleton the first time you call it, and if you do more than that, the performance will be delayed, and then it will be the same as hungry.