Design Patterns @ Chapter 5: Singleton design pattern

Chapter 5: Singleton design pattern

A single design pattern Introduction

Singleton design pattern called class, is to take certain methods to ensure that the entire software system, there is only a certain class of object instance , and the class provides only one method (static method) to obtain its object instance.

Such as Hibernate's SessionFactory, it acts as a proxy data storage source, and is responsible for creating Session objects. SessionFactory not lightweight, under normal circumstances, a project usually requires only a SessionFactory is enough, this is will be used to singleton.

Second, eight ways singleton design pattern

There are eight ways singleton pattern:

  • Hungry man type (static constants)
  • Starving formula (static code block)
  • Lazy man's (thread safe)
  • Lazy man's (thread-safe, synchronization method)
  • Lazy formula (thread-safe, synchronized block)
  • Double-checking
  • Static inner classes
  • enumerate

Third, the hungry man type (static constants)

(A) starving formula (static constant) The procedure of Example Application:

  • Constructor privatization (prevent new)
  • Internal class to create objects
  • Exposing a public static method outwardly. getInstance

Code

package com.gjxaiou.singleton.type1;

public class SingletonTest01 {

    public static void main(String[] args) {
        //测试
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

//饿汉式(静态变量)
class Singleton {
    //1. 构造器私有化, 外部能new
    private Singleton() {       
    }
    
    //2.本类内部创建对象实例
    private final static Singleton instance = new Singleton();
    
    //3. 提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return instance;
    }   
}

// output:
true
instance.hashCode=325040804
instance2.hashCode=325040804

(B) explain the advantages and disadvantages

  • Advantages: such an approach is relatively simple, that is, when the loading is completed the class is instantiated. To avoid the thread synchronization issues.
  • Disadvantages:
    • Completed when the class is instantiated loading, the effect did not reach the Lazy Loading. If you have never used this example from start to finish, it will result in a waste of memory
    • In this way based on classloder mechanism avoids the synchronization problem multithreading, however, instance to instance of the class is loaded at the time, in most cases a single mode are calling getInstance method, but there are several reasons why the class is loaded, and therefore can not there are other ways to determine (or other static methods) cause the class loader, it will not reach instance initialization lazy loading effect
  • Conclusion: This single-case model available, may result in wasted memory

Fourth, the starving of formula (static code block)

Code demonstrates:

package com.gjxaiou.singleton.type2;

public class SingletonTest02 {

    public static void main(String[] args) {
        //测试
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

//饿汉式(静态变量)
class Singleton {
    //1. 构造器私有化, 外部能new
    private Singleton() {   
    }
    

    //2.本类内部创建对象实例
    private  static Singleton instance;
    
    static { // 在静态代码块中,创建单例对象
        instance = new Singleton();
    }
    
    //3. 提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return instance;
    }
    
}

Explain the advantages and disadvantages:

1) The above embodiment and this embodiment are actually quite similar, except that the process of the class is instantiated on static code block, when the class is loaded, to execute the code block static code, instance initialization class. Advantages and disadvantages and the above is the same.

2) Conclusion: Single This embodiment mode can be used, but may result in wasted memory

(A) lazy man's (thread safe)

Ø code demonstrates:

package com.gjxaiou.singleton.type3;


public class SingletonTest03 {

    public static void main(String[] args) {
        System.out.println("懒汉式1 , 线程不安全~");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }

}

class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    //提供一个静态的公有方法,当使用到该方法时,才去创建 instance
    //即懒汉式
    public static Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Explain the advantages and disadvantages:

  • Played a Lazy Loading effect, but can only be used in single-threaded.

  • If, in multi-threaded, a thread into the if (singleton == null) Analyzing statement block, had time to perform down, but also by another thread of this sentence is determined, at this time will generate a plurality of instances . So in a multithreaded environment can not be used in this way
  • Conclusion: In the actual development, do not use this approach.

5.6 lazy man's (thread-safe, synchronization method)

Ø code demonstrates:

package com.gjxaiou.singleton.type4;

public class SingletonTest04 {

    public static void main(String[] args) {
        System.out.println("懒汉式2 , 线程安全~");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
    }
}

// 懒汉式(线程安全,同步方法)
class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    //提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题
    //即懒汉式
    public static synchronized Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Explain the advantages and disadvantages:

  • Solve thread safety issues

  • Efficiency is too low, and want to get in each thread instance of the class time to implement getInstance () method must be synchronized. And in fact, this method only once instance of code is enough, I want to get behind this kind of instance, direct return on the line. Synchronization method efficiency is too low

  • Conclusion: In the actual development, is not recommended for use in this way

Seven, lazy man's (thread-safe, synchronized block)

Not recommended

Eight double-checked

Ø code demonstrates

package com.gjxaiou.singleton.type6;


public class SingletonTest06 {

    public static void main(String[] args) {
        System.out.println("双重检查");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
        
    }

}

// 懒汉式(线程安全,同步方法)
class Singleton {
    private static volatile Singleton instance;
    
    private Singleton() {}
    
    //提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
    //同时保证了效率, 推荐使用
    
    public static synchronized Singleton getInstance() {
        if(instance == null) {
            synchronized (Singleton.class) {
                if(instance == null) {
                    instance = new Singleton();
                }
            }
            
        }
        return instance;
    }
}

Explain the advantages and disadvantages:

  • Double-Check concept is often used to develop multi-threaded, as shown in the code, we conducted two if (singleton == null) examination, so as to ensure the security thread.

  • Thus, with examples of code is executed only once, when accessed again later, it is judged if (singleton == null), the direct return object instance, the method avoids the repeated synchronization.

  • Thread-safe; lazy loading; high efficiency

  • Conclusion: In the actual development, recommend the use of such a single mode design embodiment of formula

Nine, static inner classes

Code demonstrates:

package com.gjxaiou.singleton.type7;


public class SingletonTest07 {

    public static void main(String[] args) {
        System.out.println("使用静态内部类完成单例模式");
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2); // true
        System.out.println("instance.hashCode=" + instance.hashCode());
        System.out.println("instance2.hashCode=" + instance2.hashCode());
        
    }

}

// 静态内部类完成, 推荐使用
class Singleton {
    private static volatile Singleton instance;
    
    //构造器私有化
    private Singleton() {}
    
    //写一个静态内部类,该类中有一个静态属性 Singleton
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton(); 
    }
    
    //提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
    
    public static synchronized Singleton getInstance() {
        
        return SingletonInstance.INSTANCE;
    }
}

Explain the advantages and disadvantages:

  • This method uses a class loading mechanism to ensure that only one thread instance initialization.

  • Static inner classes manner when Singleton class is loaded and instantiated not immediately, but when the need to instantiate, call the getInstance method will load SingletonInstance class to complete instantiation of Singleton.

  • Static properties of the class is first loaded only when the class is initialized, so here, JVM helps us ensure the security thread, when the class is initialized, the other thread is inaccessible. (Loading class when it is safe)

  • Advantages: Avoid the thread-safe, use a static inner classes Features implement lazy loading, high efficiency

  • Conclusion: The recommended use.

Ten, enumeration

Code demonstrates

package com.gjxaiou.singleton.type8;

public class SingletonTest08 {
    public static void main(String[] args) {
        Singleton instance = Singleton.INSTANCE;
        Singleton instance2 = Singleton.INSTANCE;
        System.out.println(instance == instance2);
        
        System.out.println(instance.hashCode());
        System.out.println(instance2.hashCode());
        
        instance.sayOK();
    }
}

//使用枚举,可以实现单例, 推荐
enum Singleton {
    INSTANCE; //属性
    public void sayOK() {
        System.out.println("ok~");
    }
}

Explain the advantages and disadvantages:

1) This enumeration means JDK1.5 added to achieve single-mode embodiment. Not only to avoid multi-thread synchronization problems, but also to prevent deserialization re-create a new object.

2) This approach is Effective Java author Josh Bloch promoted the way

3) Conclusion: Recommended Use

XI singleton pattern in the source application JDK Analysis

(A) Single source mode embodiment JDK Application Analysis

1) We in the JDK, java.lang.Runtime is the classic Singleton (starving style)

2) code analysis + + source code shows the Debug

(B) Precautions Singleton and detail description

1) Singleton pattern to ensure that the memory system there is only one object class, saving system resources, to create some objects that require frequent destruction, single-use-case model can improve system performance

2) When a single embodiment want to instantiate class, you must remember to use the corresponding method for acquiring an object, instead of using the new

3) singleton pattern of usage scenarios : the need for frequent creation and destruction of objects , consuming too much or consume too many resources (that is, when you create an object: heavyweight objects), but frequently used objects, tools Objects , frequent access to the database files or objects (such as the data source, session factories , etc.)

Guess you like

Origin www.cnblogs.com/qq438649499/p/12178272.html