单例模式

  1. 懒汉模式
/**
 * @Description 懒汉模式 实现了延迟加载,但是效率较低
 */
public class LazySingleton {

    private static LazySingleton lazySingleton;

    private LazySingleton(){

    }

    public synchronized static LazySingleton getLazySingleton(){
        if(lazySingleton == null){
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }

    public static void main(String[] args) {
        LazySingleton h1 = LazySingleton.getLazySingleton();
        LazySingleton h2 = LazySingleton.getLazySingleton();
        System.out.println(h1==h2);
    }
}
  1. 饿汉模式
1
/**
 * @Description  饿汉模式
 * 类加载时完成实例化,避免多线程同步问题
 */
public class HungrySingleton {

    private static HungrySingleton singleton = new HungrySingleton();

    private HungrySingleton(){
    }

    public static HungrySingleton getSingleton(){
        return singleton;
    }

    public static void main(String[] args) {
        HungrySingleton h1 = HungrySingleton.getSingleton();
        HungrySingleton h2 = HungrySingleton.getSingleton();
        System.out.println(h1==h2);
    }
}
  1. 双重校验锁模式
/**
* @description: 1.懒加载, 2 volatile 保证了指令不会重排
*/
public class DoubleCheckSingleton {

    private volatile static DoubleCheckSingleton singleton;

    private DoubleCheckSingleton() {
    }

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

    public static void main(String[] args) {
       DoubleCheckSingleton d1 = DoubleCheckSingleton.getInstance();
       DoubleCheckSingleton d2 = DoubleCheckSingleton.getInstance();
        System.out.println(d1==d2);
    }

}

 singleton = new DoubleCheckSingleton();实际过程分为3步
1.为singleton分配内存空间
2.初始化singleton
3.singleton指向分配的内存地址
由于jvm具有指令重排的特性,因此指令可能变成1->3->2。指令重排在单线程下不会出现问题,但多线程环境中会造成一个线程获得没有初始化的实例
使用volatile可以禁止指令重排,在多线程环境下也能正常运行
  1. 内部类模式
/***
* @description: 外部类加载时不会加载内部类,使用内部类时才会加载, 保证了懒加载
 * 类加载时实例化对象,不会造成线程安全问题
*/
public class InnerClassSingleton {

    private InnerClassSingleton(){

    }

    private static class innerInstance {
        private static final InnerClassSingleton singleton = new InnerClassSingleton();
    }

    public static InnerClassSingleton getInstance(){
        return innerInstance.singleton;
    }

    public static void main(String[] args) {
        InnerClassSingleton i1 = InnerClassSingleton.getInstance();
        InnerClassSingleton i2 = InnerClassSingleton.getInstance();
        System.out.println(i1==i2);
    }
}

你可能感兴趣的