Introduction and reflection of the singleton pattern in java

As we all know, there are 7 types of singleton pattern implementations in java, as follows:

1. Lazy mode (thread unsafe)

        public class Singleton{

                   private static Singleton instance;

                   private Singleton(){};

                   public static Singleton getInstance(){

                              if(instance == null ){

                                     instance = new Singleton();

                               }

                        return instance;

                    }

         }

This mode uses lazy loading but is not safe under multi-threading

2, lazy mode (thread safety)

 public class Singleton{

                   private static Singleton instance;

                   private Singleton(){};

                   public static synchronized Singleton getInstance(){

                              if(instance == null ){

                                     instance = new Singleton();

                               }

                        return instance;

                    }

         }

Lazy loading, thread-safe, but extremely inefficient, the synchronization lock locks the object, and every time the object is fetched, it is locked, so the efficiency is low

3. Hungry man mode

public class Singleton{

                   private static Singleton instance= new Singleton();

                   private Singleton(){};

                   public static Singleton getInstance(){

                       return instance;

                    }

         }

This method avoids the multi-thread synchronization problem based on the classloader mechanism, but the instance is instantiated when the class is loaded, which does not achieve the effect of lazy loading.

4. Hungry man mode variant

public class Singleton{

                   private static Singleton instance = null;

                   static{

                        instance= new Singleton();

                   }

                   private Singleton(){};

                   public static Singleton getInstance(){

                       return instance;

                    }

         }

equivalent to the third

5. Static inner class

public class Singleton{

                   private Singleton(){};

                   public static synchronized Singleton getInstance(){

                       return SingletonInnerClass.instance;

                    }

                  private static class SingletonInnerClass(){

                       private static Singleton instance = new Singleton();

                  }

         }

 The classloader mechanism is used to ensure that there is only one instance when an instance is initialized. The difference from the third and fourth methods is that the lazy loading effect is achieved (the third and fourth methods will be instantiated as long as the singleton class is loaded, and this The SingletonInnerClass class is not actively used, and the SingletonInnerClass class will only be displayed when the getInstance is called, so as to realize lazy loading.) It consumes resources when instantiating an instance, and I want it to be loaded lazily. In addition, I don’t want to instantiate the singleton class when it is loaded. , this method seems very reasonable. Recommended Use

6. Double check lock

public class Singleton{

                   private static Singleton instance;

                   private Singleton(){};

                   public static synchronized Singleton getInstance(){

                      if(instance == null){

                              synchronized(Singleton.class){

                                     if(instance == null){

                                           instance = new Singleton();

                                      }

                                }

                      }

                       return instance;

                    }

         }

No matter how superior the performance is, using the synchronized modifier will affect the performance to some extent.

7. Enumeration

    public enum SIngleton{

             INSTANCE;

             public void whateverMethod(){}

}

This method is advocated by Effective Java, which can not only avoid multi-thread synchronization problems, but also prevent deserialization from recreating new objects, but it is not recommended for readability reasons.

From this, the seven methods have been introduced, but there are also several issues that need to be reflected

1. How to guarantee a singleton in the reflection state?

2. How to guarantee singleton in deserialization?

For the first question we can do the following

public class Singleton3{

             private static boolean initialized = false;

             private Singleton3(){

                    synchronized(Singleton3.class){

                             if(initialized == false){

                                  initialized = !initialized ;

                             }else{

                                  throw new RuntimeException("Singleton has been destroyed");

                             }

                       }

                 }

             static class SingletonHolder{

                   private static final Singleton3 instance = new Singleton3();

              }

             public static Singleton3 getInstance(){

                           return SingletonHolder.instance;

             }

}

This ensures that reflection cannot destroy its singleton

For the second problem, we need to provide an implementation of the readResolve() method instead of reading the object from the stream, which ensures that no one can create a new instance during serialization and deserialization

public class Singleton4 implements Serializable{

             private static boolean initialized = false;

             private Singleton4(){

                    synchronized(Singleton4.class){

                             if(initialized == false){

                                  initialized = !initialized ;

                             }else{

                                  throw new RuntimeException("Singleton has been destroyed");

                             }

                       }

                 }

             static class SingletonHolder{

                   private static final Singleton4 instance = new Singleton4();

              }

             public static Singleton4 getInstance(){

                           return SingletonHolder.instance;

             }

            private Object readResolve(){

                   return getInstance();

             }

}

This article gives a variety of singleton modes, generally from static inner classes and guaranteed reflection, and singleton selection in serialized state. You can choose one of the three according to the actual situation. It is not necessary to choose the last one as a singleton implementation.

   


    

                              


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325383360&siteId=291194637