The singleton pattern
Description:
The singleton pattern, as the name implies, guarantees that there is only one instance object globally and provides access to that object
Features:
- Class constructor privatized
- Private static variable
- Provide common methods to access the instance
Implementation:
Ⅰ LanHanShi
Thread unsafe; Lazy loading
package com.bookmark.designpatterns.singleton;
/ * * *@author: hj
* @date: 2020-12-19 * to them@description: 1. Lazy, thread unsafe **/
public class SingletonImpl1 {
// Private variables
private static SingletonImpl1 singletonImpl1;
// Privatize the constructor
private SingletonImpl1(a) {}// Public static methods
public static SingletonImpl1 getUniqueInstance(a) {
if (singletonImpl1 == null) { // The thread is not safe. It is possible to create multiple instances
singletonImpl1 = new SingletonImpl1();
}
returnsingletonImpl1; }}Copy the code
Ⅱ hungry Chinese type
Thread-safe, but resource-consuming, instances are created before they are used
package com.bookmark.designpatterns.singleton;
/ * * *@author: hj
* @date: the 2020-12-19 bowing *@description: Hunhun-style - thread-safe but resource-intensive, created without using the instance **/
public class SingletonImpl2 {
private static SingletonImpl2 singletonImpl2 = new SingletonImpl2();
private SingletonImpl2(a) {}public static SingletonImpl2 getInstance(a){
returnsingletonImpl2; }}Copy the code
Ⅲ LanHanShi
This is a thread-safe implementation method that adds a synchronization lock to the method of obtaining an instance. This method has poor performance and is not recommended
package com.bookmark.designpatterns.singleton;
/ * * *@author: hj
* @date: the 2020-12-19 and *@description: lazy - thread-safe, locking methods **/
public class SingletonImpl3 {
private static SingletonImpl3 singletonImpl3;
private SingletonImpl3(a) {}public static synchronized SingletonImpl3 getInstance(a) { // Add a lock to the method to ensure thread-safety. However, adding a lock to the method degrades performance and is not recommended
if (singletonImpl3 == null) {
singletonImpl3 = new SingletonImpl3();
}
returnsingletonImpl3; }}Copy the code
ⅳ Double check lock
Thread safe, using the volatile keyword to prevent JVM instruction reordering
package com.bookmark.designpatterns.singleton;
/ * * *@author: hj
* @date: the 2020-12-19 double-break *@description: * Double-checked locking - thread-safe * Volatile keyword prevents JVM instruction reordering **/
public class SingletonImpl4 {
private volatile static SingletonImpl4 singletonImpl4;
private SingletonImpl4(a) {}public static SingletonImpl4 getInstance(a) {
if (singletonImpl4 == null) {
synchronized (SingletonImpl4.class) {// Locking the instantiated part of the code is more efficient than locking the method directly
if (singletonImpl4 == null) {// This is to prevent multiple threads from entering the first if condition, causing multiple instances to be created
singletonImpl4 = newSingletonImpl4(); }}}returnsingletonImpl4; }}Copy the code
V Static inner class implementation
Delayed loading, thread safe
package com.bookmark.designpatterns.singleton;
/ * * *@author: hj
* @date: the 2020-12-26 who were *@description: Static inner class implementation involves class loading related issues delayed loading, thread safe * * 1. When the parent class is loaded, the SingletonHolder is not loaded, which does not take up memory * 2. INSTANCE is initialized when getInstance is called * 3. This implementation is guaranteed to be thread safe **/ because of the JVM class loading mechanism
public class SingletonImpl5 {
private SingletonImpl5(a) {}private static class SingletonHolder{
private static final SingletonImpl5 INSTANCE = new SingletonImpl5();
}
public static SingletonImpl5 getInstance(a) {
returnSingletonHolder.INSTANCE; }}Copy the code
ⅵ Enumeration Implementation
It is thread safe, prevents reflection attacks, and does not create multiple instances after multiple serialization and deserialization
package com.bookmark.designpatterns.singleton;
/ * * *@author: hj
* @date: the 2020-12-26 16:07 *@description: Enumeration implementation * 1. Thread safety * 2. Can prevent reflection attack, other implementations cannot guarantee, need to add code in the constructor to prevent multiple instantiations - reflection attack: through reflection, using setAccessible() method can set the private constructor orientation level to public * 3. Multiple objects are not created after multiple serialization and deserialization; Other implementations use the transient keyword to modify all variables **/
public enum SingletonImpl6 {
/** * Instance */
INSTANCE;
private String objName;
private String getObjName(a) {
return objName;
}
private void setObjName(String objName) {
this.objName = objName;
}
public static void main(String[] args) {
// Singleton test
SingletonImpl6 firstSingleton = SingletonImpl6.INSTANCE;
firstSingleton.setObjName("first name");
System.out.println("firstSingleton = " + firstSingleton.getObjName());
SingletonImpl6 secondSingleton = SingletonImpl6.INSTANCE;
secondSingleton.setObjName("second name");
System.out.println("firstSingleton = " + firstSingleton.getObjName());
System.out.println("secondSingleton = " + secondSingleton.getObjName());
// Reflect to get the instance test
SingletonImpl6[] enumConstants = SingletonImpl6.class.getEnumConstants();
for (SingletonImpl6 enumConstant : enumConstants) {
System.out.println("objName = "+ enumConstant.getObjName()); }}}Copy the code
conclusion
Thread safety: 2, 3, 4,5,6
To prevent reflection attacks, serialization and unsequence words do not create multiple objects only enumeration implementation