catalogue
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 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?
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 Is reflection safe?
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?
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