Design mode - singleton mode

catalogue

1. Background:

2. Definition of singleton mode:

3. Lazy man - several problems in the single case development process:

        

three point one   Single thread single instance mode creation

three point two   Test whether the single instance mode can maintain the definition in the case of multithreading

  three point three   How to guarantee the definition in the case of multithreading

4. Several problems in the single case development process:

four point one   How to create and test single thread single instance mode?

4.2 test whether the single instance mode can maintain the definition in the case of multithreading?

5. Several problems in the static internal class - singleton development process:

five point one   How to create and test single thread single instance mode?

five point two   Test whether the single instance mode can maintain the definition in the case of multithreading?  

6. Reflection safety

6.1 is there any other method in the above singleton mode that can be instantiated directly without the getInstance() method?

six point two   If there are methods, whether it is proved that the above mode is unsafe and whether it can be protected?

7.ENUM - several problems in the single instance development process:

7.1 how to create and test single thread single instance mode?

  seven point three   2. Test whether the single instance mode can maintain the definition in the case of multithreading?

seven point three   Is reflection safe?

8. Anti sequence security

  8.1 can different instances be created after anti sequence to destroy the single instance mode?

  eight point two   If the anti sequence destroys the singleton mode, how to protect it?

9. Single case scenario

1. Background:

         When you meet the golden nine silver ten, brush the design mode and record the learning of single case mode

2. Definition of singleton mode:

         Ensure that there is only one instance of a class and provide a global access point.

3. Lazy man - several problems in the single case development process:

        1. How to create and test the single thread single instance mode?

        2. Test whether the single instance mode can maintain the definition in the case of multithreading?

        3. How to ensure the definition in the case of multithreading?

        

three point one   Single thread single instance mode creation

package com.company;

/**
 * Lazy mode
 */
public class LaySingleTonTest {
    public static void main(String[] args) {
        LaySingleTon singleTon = LaySingleTon.getInstance();
        LaySingleTon singleTon2 = LaySingleTon.getInstance();
        System.out.println(singleTon == singleTon2);
    }
}

class LaySingleTon{
    private static  LaySingleTon instance;
    private  LaySingleTon(){

    }

    public static LaySingleTon getInstance(){
        if(instance == null){
            instance = new LaySingleTon();
        }
        return instance;
    }
}

Return result:

true

three point two   Test whether the single instance mode can maintain the definition in the case of multithreading

package com.company;

/**
 * Lazy mode
 */
public class LaySingleTonTest {
    public static void main(String[] args) {

        new Thread(()->{
            LaySingleTon singleTon = LaySingleTon.getInstance();
            System.out.println(singleTon);
        }).start();

        new Thread(()->{
            LaySingleTon singleTon = LaySingleTon.getInstance();
            System.out.println(singleTon);
        }).start();
    }
}

class LaySingleTon{
    private static  LaySingleTon instance;
    private  LaySingleTon(){

    }

    public static LaySingleTon getInstance(){
        if(instance == null){
            instance = new LaySingleTon();
        }
        return instance;
    }
}

Test result: the memory addresses are not the same

com.company.LaySingleTon@4bfa3118
com.company.LaySingleTon@fdd9762

  three point three   How to guarantee the definition in the case of multithreading

package com.company;

/**
 * Lazy mode
 */
public class LaySingleTonTest {
    public static void main(String[] args) {

        new Thread(()->{
            LaySingleTon singleTon = LaySingleTon.getInstance();
            System.out.println(singleTon);
        }).start();

        new Thread(()->{
            LaySingleTon singleTon = LaySingleTon.getInstance();
            System.out.println(singleTon);
        }).start();
    }
}

class LaySingleTon{
    private static  LaySingleTon instance;
    private  LaySingleTon(){

    }

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

Test results:

com.company.LaySingleTon@91e64ad
com.company.LaySingleTon@91e64ad

  Summary: only one instance can be provided through synchronized keyword and double check mechanism.

4. Several problems in the single case development process:

        1. How to create and test the single thread single instance mode?

        2. Test whether the single instance mode can maintain the definition in the case of multithreading?

four point one   How to create and test single thread single instance mode?

package com.company;

public class HungrySingleTonTest {

    public static void main(String[] args) {
        HungrySingleTon instance = HungrySingleTon.getInstance();
        HungrySingleTon instance1 = HungrySingleTon.getInstance();
        System.out.println(instance == instance1);
    }
}

class HungrySingleTon{
    private static HungrySingleTon instance = new HungrySingleTon();
    private HungrySingleTon(){

    }

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

Test results:

true

4.2 test whether the single instance mode can maintain the definition in the case of multithreading?

package com.company;

public class HungrySingleTonTest {

    public static void main(String[] args) {
//        HungrySingleTon instance = HungrySingleTon.getInstance();
//        HungrySingleTon instance1 = HungrySingleTon.getInstance();
//        System.out.println(instance == instance1);
        new Thread(()->{
            HungrySingleTon singleTon = HungrySingleTon.getInstance();
            System.out.println(singleTon);
        }).start();

        new Thread(()->{
            HungrySingleTon singleTon = HungrySingleTon.getInstance();
            System.out.println(singleTon);
        }).start();
    }
}

class HungrySingleTon{
    private static HungrySingleTon instance = new HungrySingleTon();
    private HungrySingleTon(){

    }

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

Test result: the memory address is the same.

com.company.HungrySingleTon@5f39fd8b
com.company.HungrySingleTon@5f39fd8b

Summary: hungry Han mode adopts class loading mechanism to ensure that an example can be obtained in the case of single thread and multi thread

5. Several problems in the static internal class - singleton development process:

        1. How to create and test the single thread single instance mode?

        2. Test whether the single instance mode can maintain the definition in the case of multithreading?

five point one   How to create and test single thread single instance mode?

package com.company;

public class staticInnerClassSingleTonTest {
    public static void main(String[] args) {
        staticInnerClassSingleTon instance = staticInnerClassSingleTon.getInstance();
        staticInnerClassSingleTon instance1 = staticInnerClassSingleTon.getInstance();
        System.out.println(instance == instance1);
    }
}

class staticInnerClassSingleTon{
    public static class InnerClassSingleTon{
        private static staticInnerClassSingleTon instance = new staticInnerClassSingleTon();
    }

    private staticInnerClassSingleTon(){

    }

    public static staticInnerClassSingleTon getInstance(){
        return InnerClassSingleTon.instance;
    }
}

Test results:

true

five point two   Test whether the single instance mode can maintain the definition in the case of multithreading?  

package com.company;

public class staticInnerClassSingleTonTest {
    public static void main(String[] args) {
//        staticInnerClassSingleTon instance = staticInnerClassSingleTon.getInstance();
//        staticInnerClassSingleTon instance1 = staticInnerClassSingleTon.getInstance();
//        System.out.println(instance == instance1);
        new Thread(()->{
            staticInnerClassSingleTon singleTon = staticInnerClassSingleTon.getInstance();
            System.out.println(singleTon);
        }).start();

        new Thread(()->{
            staticInnerClassSingleTon singleTon = staticInnerClassSingleTon.getInstance();
            System.out.println(singleTon);
        }).start();
    }
}

class staticInnerClassSingleTon{
    public static class InnerClassSingleTon{
        private static staticInnerClassSingleTon instance = new staticInnerClassSingleTon();
    }

    private staticInnerClassSingleTon(){

    }

    public static staticInnerClassSingleTon getInstance(){
        return InnerClassSingleTon.instance;
    }
}

Test results:

com.company.staticInnerClassSingleTon@4dd77a3a
com.company.staticInnerClassSingleTon@4dd77a3a

  Summary:

         The loading method of static internal classes also uses the class loading mechanism to ensure thread safety.

6. Reflection safety

        1. Is there any other method in the above singleton mode that can be instantiated directly without the getInstance() method?

        2. If there are methods, whether it is proved that the above mode is unsafe and whether it can be protected?

6.1 is there any other method in the above singleton mode that can be instantiated directly without the getInstance() method?

package com.company;


import java.lang.reflect.Constructor;

public class staticInnerClassSingleTonTest {
    public static void main(String[] args) throws Exception{
        Constructor<staticInnerClassSingleTon> constructor = staticInnerClassSingleTon.class.getDeclaredConstructor();
        constructor.setAccessible(true);//Change permissions
        staticInnerClassSingleTon instance = constructor.newInstance();

        staticInnerClassSingleTon instance1 =staticInnerClassSingleTon.getInstance();
        System.out.println(instance == instance1);
    }
}

class staticInnerClassSingleTon{
    public static class InnerClassSingleTon{
        private static staticInnerClassSingleTon instance = new staticInnerClassSingleTon();
    }

    private staticInnerClassSingleTon(){

    }

    public static staticInnerClassSingleTon getInstance(){
        return InnerClassSingleTon.instance;
    }
}

Test result: it can be instantiated through reflection mechanism

false

six point two   If there are methods, whether it is proved that the above mode is unsafe and whether it can be protected?

package com.company;


import java.lang.reflect.Constructor;

public class staticInnerClassSingleTonTest {
    public static void main(String[] args) throws Exception{
        Constructor<staticInnerClassSingleTon> constructor = staticInnerClassSingleTon.class.getDeclaredConstructor();
        constructor.setAccessible(true);//Change permissions
        staticInnerClassSingleTon instance = constructor.newInstance();

        staticInnerClassSingleTon instance1 =staticInnerClassSingleTon.getInstance();
        System.out.println(instance == instance1);
    }
}

class staticInnerClassSingleTon{
    public static class InnerClassSingleTon{
        private static staticInnerClassSingleTon instance = new staticInnerClassSingleTon();
    }

    private staticInnerClassSingleTon(){
        if(InnerClassSingleTon.instance != null){
            throw new RuntimeException("Cannot have multiple instances");
        }
    }

    public static staticInnerClassSingleTon getInstance(){
        return InnerClassSingleTon.instance;
    }
}

Test results:

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
    at com.company.staticInnerClassSingleTonTest.main(staticInnerClassSingleTonTest.java:10)
Caused by: java.lang.RuntimeException: cannot have multiple instances
    at com.company.staticInnerClassSingleTon.<init>(staticInnerClassSingleTonTest.java:24)
    ... 5 more

  Summary:

        Hungry Han mode and static inner class singleton mode can throw exceptions by adding a checking mechanism to the constructor to prevent reflection from creating instances. Lazy mode does not create instances during class loading and cannot prevent reflection from creating instances.

7.ENUM - several problems in the single instance development process:

        1. How to create and test the single thread single instance mode?

        2. Test whether the single instance mode can maintain the definition in the case of multithreading?

        3. Is reflection safe?

7.1 how to create and test single thread single instance mode?

package com.company;

public class EnumSingleTonTest {
    public static void main(String[] args) {
        EnumSingleTon instance = EnumSingleTon.INSTANCE;
        EnumSingleTon instance1 = EnumSingleTon.INSTANCE;
        System.out.println(instance == instance1);
    }
}
enum EnumSingleTon{
    INSTANCE;

}

Test results:

true

  seven point three   2. Test whether the single instance mode can maintain the definition in the case of multithreading?

package com.company;

public class EnumSingleTonTest {
    public static void main(String[] args) {
//        EnumSingleTon instance = EnumSingleTon.INSTANCE;
//        EnumSingleTon instance1 = EnumSingleTon.INSTANCE;
//        System.out.println(instance == instance1);

        new Thread(()->{
            EnumSingleTon singleTon = EnumSingleTon.INSTANCE;
            System.out.println(singleTon);
        }).start();

        new Thread(()->{
            EnumSingleTon singleTon = EnumSingleTon.INSTANCE;
            System.out.println(singleTon);
        }).start();
    }
}
enum EnumSingleTon{
    INSTANCE;

}

Test results:

INSTANCE
INSTANCE

seven point three   Is reflection safe?

package com.company;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class EnumSingleTonTest {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

        Constructor<EnumSingleTon> constructor = EnumSingleTon.class.getDeclaredConstructor();
        constructor.setAccessible(true);//Change permissions
        EnumSingleTon instance = constructor.newInstance();

        EnumSingleTon instance1 =EnumSingleTon.INSTANCE;
        System.out.println(instance == instance1);
    }
}
enum EnumSingleTon{
    INSTANCE;

}

Test result: the creation of ENUM reflection form is not supported, and an exception is finally thrown. Side reflection proves safe.

Exception in thread "main" java.lang.NoSuchMethodException: com.company.EnumSingleTon.<init>()
    at java.base/java.lang.Class.getConstructor0(Class.java:3322)
    at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2510)
    at com.company.EnumSingleTonTest.main(EnumSingleTonTest.java:22)

8. Anti sequence security

        one   Can different instances be created after anti sequence to destroy the single instance mode?

        2. If the anti sequence destroys the singleton mode, how to protect it?

  8.1 can different instances be created after anti sequence to destroy the single instance mode?

package com.company;


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

public class staticInnerClassSingleTonTest {
    public static void main(String[] args) throws Exception{
        staticInnerClassSingleTon instance = staticInnerClassSingleTon.getInstance();

         //1. Create a testSerializable serialized file
//        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("testSerializable"));
//        objectOutputStream.writeObject(instance);
//        objectOutputStream.close();

        // 2. Deserialize the file to instantiate the class
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("testSerializable"));
        staticInnerClassSingleTon instance1 = (staticInnerClassSingleTon)objectInputStream.readObject();

        System.out.println(instance == instance1);
    }
}

class staticInnerClassSingleTon implements Serializable {
    public static class InnerClassSingleTon{
        private static staticInnerClassSingleTon instance = new staticInnerClassSingleTon();
    }

    private staticInnerClassSingleTon(){
        if(InnerClassSingleTon.instance != null){
            throw new RuntimeException("Cannot have multiple instances");
        }
    }

    public static staticInnerClassSingleTon getInstance(){
        return InnerClassSingleTon.instance;
    }
}

Test result: destroy single case mode

false

  eight point two   If the anti sequence destroys the singleton mode, how to protect it?

package com.company;


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

public class staticInnerClassSingleTonTest {
    public static void main(String[] args) throws Exception{
        staticInnerClassSingleTon instance = staticInnerClassSingleTon.getInstance();

         //1. Create a testSerializable serialized file
//        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("testSerializable"));
//        objectOutputStream.writeObject(instance);
//        objectOutputStream.close();

        // 2. Deserialize the file to instantiate the class
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("testSerializable"));
        staticInnerClassSingleTon instance1 = (staticInnerClassSingleTon)objectInputStream.readObject();

        System.out.println(instance == instance1);
    }
}

class staticInnerClassSingleTon implements Serializable {

    static final long serialVersionUID = 42L;

    public static class InnerClassSingleTon{
        private static staticInnerClassSingleTon instance = new staticInnerClassSingleTon();
    }

    private staticInnerClassSingleTon(){
        if(InnerClassSingleTon.instance != null){
            throw new RuntimeException("Cannot have multiple instances");
        }
    }

    public static staticInnerClassSingleTon getInstance(){
        return InnerClassSingleTon.instance;
    }

    Object readResolve() throws ObjectStreamException{
        return InnerClassSingleTon.instance;
    }

}

Test results:

true

Summary: by definition   readResolve method to ensure.

9. Single case scenario

JDK : java.lang.Runtime

Spring:ReactiveAdapterRegistry-getSharedInstance

Keywords: Java Design Pattern

Added by mckintosh18 on Sun, 10 Oct 2021 17:43:37 +0300