Four ways to create singleton pattern

Keywords: Java jvm Session

This is a question for my recent interview
There are several ways to create a single example of the interviewer's question. I answered the lazy man and the hungry man. He told me that there are two kinds. In fact, I still vaguely remember two kinds. I just can't remember, and my heart silently tears..... Here are the excerpts and Blogs: Four ways to create java singleton pattern

This article is simple and easy to understand

Starved Han style single instance mode

package com.company.singleton;

/**
 * Singleton mode
 * Evil Chinese style
 */
public class Singleton_hungry {
    private static Singleton_hungry instance = new Singleton_hungry();

    //Construction method of privatization
    private Singleton_hungry(){

    }

    public static Singleton_hungry getInstance(){
        return instance;
    }
}

Lazy man implementation singleton mode

package com.company.singleton;

import java.io.Serializable;

/**
 * Single instance implementation
 * Lazy man (double lock detection mechanism)
 */
public class Singleton_lazy implements Serializable,Cloneable {
    private volatile static Singleton_lazy instance = null;
    //Privatization construction method
    private Singleton_lazy(){

    }
    public static Singleton_lazy getInstance(){
        if(instance == null){
            synchronized (Singleton_lazy.class){
                if(instance == null){
                    instance = new Singleton_lazy();
                }
            }
        }
        return instance;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}


Optimized lazy implementation of singleton mode

package com.company.singleton;

import java.io.Serializable;

/**
 * Singleton implementation
 * Lazy (double lock detection mechanism)
 *
 * 1.Prevent reflection
 * Define a global variable and throw an exception when it is created for the second time
 * 2.Prevent cloning
 * Override clone() to return singleton directly
 * 3.Prevent serialization corruption
 * Add readResolve() to return the Object object Object
 *
 */
public class Singleton_lazy2 implements Serializable,Cloneable {
    private volatile static Singleton_lazy2 instance = null;
    private static volatile boolean isCreate = false;
    //Construction method of privatization
    private Singleton_lazy2(){
        if(isCreate){
            throw new RuntimeException("It has been instantiated once. It can't be instantiated any more");
        }
        isCreate = true;

    }
    public static Singleton_lazy2 getInstance(){
        if(instance == null){
            synchronized (Singleton_lazy2.class){
                if(instance == null){
                    instance = new Singleton_lazy2();
                }
            }
        }
        return instance;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return instance;
    }

    private Object readResolve(){
        return instance;
    }


}

Static inner class implements singleton pattern

package com.company.singleton;

/**
 * Singleton mode
 * Using static inner class to implement singleton pattern
 */
public class Singleton_static {
    private static class SingletonHolder{
        /**
         * Static initializer with JVM to ensure thread safety
         */
        private static Singleton_static  instance = new Singleton_static();
    }

    private Singleton_static(){

    }
    public static Singleton_static getInstance(){
        return SingletonHolder.instance;
    }
}

Enumeration to implement singleton pattern

package com.company.singleton;

public enum Singleton_enum {
    uniqueInstance;//Define an enumeration element that represents an instance of Singleton

    public void singletonOperation(){
        //Functional processing
        System.err.println("Function processing");
    }


}

Test code

package com.company.singleton;

import java.io.*;
import java.lang.reflect.Constructor;

/**
 * Three ways to destroy single case mode
 * 1.reflex
 * 2.serialize
 * 3.clone
 *
 * The solution is as follows:
 * 1.Prevent reflection
 * Define a global variable and throw an exception when it is created for the second time
 * 2.Prevent clone corruption
 * Overriding clone() directly returns the singleton object
 * 3.Prevent serialization corruption
 * Add readResolve to return the Object object
 *
 */
public class SingletonTest {
    public static void main(String[] args) throws Exception {
        System.out.println("----------------serialize---------------------");
       // Singleton_lazy originSingleton = Singleton_lazy.getInstance();
        Singleton_lazy2 originSingleton = Singleton_lazy2.getInstance();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(Singleton_lazy2.getInstance());

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
    //   Singleton_lazy serializeSingleton = (Singleton_lazy)ois.readObject();
        Singleton_lazy2 serializeSingleton = (Singleton_lazy2)ois.readObject();
        System.out.println(originSingleton==serializeSingleton);

        System.out.println("---------------reflex-------------------");

      //  Constructor<Singleton_lazy> cons = Singleton_lazy.class.getDeclaredConstructor();
        Constructor<Singleton_lazy2> cons = Singleton_lazy2.class.getDeclaredConstructor();
        cons.setAccessible(true);

       // Singleton_lazy reflexSingleton = cons.newInstance();
        Singleton_lazy2 reflexSingleton = cons.newInstance();
        System.out.println(reflexSingleton == originSingleton);
        System.out.println("-----------clone-----------------------");

     //   Singleton_lazy cloneSingleton = (Singleton_lazy) originSingleton.clone();
        Singleton_lazy2 cloneSingleton = (Singleton_lazy2) originSingleton.clone();
        System.out.println(cloneSingleton == originSingleton);


    }
}

Features of the singleton model

  1. Singleton mode ensures that there is only one object in the system memory, which saves system resources. For some objects that need to be destroyed frequently, singleton pattern can improve system performance
  2. When you want to instantiate a singleton class, you must remember the corresponding method to get the object instead of using new
  3. Singleton pattern usage scenarios: objects that need to be created and destroyed frequently, objects that take too much time or resources to create objects (i.e. heavyweight objects), but often used objects, tool class objects, objects that frequently access databases or files (such as data sources, session factories, etc.)

Posted by Birdmansplace on Sun, 28 Jun 2020 22:54:54 -0700