JavaSE

SingleTon-单例设计模式

2021-05-21  本文已影响0人  AIGame孑小白

懒汉式

之所以叫做懒汉式:只有对象调用方法的时候才会获取到实例对象,所以懒。

大致雏形

public class SingleTon {
    private static SingleTon singleTon;
   public SingleTon(){}
    public static SingleTon getInstence(){
        if(singleTon==null){
            singleTon = new SingleTon();
        }
        return singleTon;
    }
}

采用DCL双重检测的写法,第一层if是提高效率,synchronized是为了保证实例化的对象在多线程并发访问的时候保持唯一性,第二层if则是判断是否需要创建实例对象。

最终成品

public class SingleTon {
    private static SingleTon singleTon;
   public SingleTon(){}
    public static SingleTon getInstence(){
        if(singleTon==null){
            synchronized (SingleTon.class) {
                if(singleTon==null){
                    singleTon = new SingleTon();
                }
            }
        }
        return singleTon;
    }
}

弊端就是:由于添加了锁,所以降低了效率。

饿汉式

public class SingleTon {
    private static SingleTon singleTon = new SingleTon();
    public SingleTon(){}
    public static SingleTon getInstence(){
        return singleTon;
    }
}

即解决了多线程同时访问造成对象不唯一,也解决了加锁使得效率低的问题。

第一种

public class SingleTon {
    private static final SingleTon INSTANCE = new SingleTon();
   //保证不让外界new出对象
    private SingleTon(){}
    public static SingleTon getInstance(){
        return INSTANCE;
    }
}

这种写法是饿汉式写法,饥饿难耐,恨不得自己创建对象。这种设计是线程安全的,实际上这是由JVM保证的,因为JVM加载所有类它都只load一次。这种写法简单实用。

第二种

public class SingleTon {
    private static SingleTon INSTANCE;
    private SingleTon(){}
    public static SingleTon getInstance(){
        if(INSTANCE==null){
            INSTANCE = new SingleTon();
        }
        return INSTANCE;
    }
}

这种写法被称之为:懒汉式,因为它是在外界调用get的时候创建的对象。但是当多线程并发访问的时候可能会导致多次创建对象。

第三种

public class SingleTon {
   //volatile:避免指令重排(JIT优化)
    private static volatile SingleTon INSTANCE;
    private SingleTon(){}
    public static SingleTon getInstance(){
        if(INSTANCE==null){
            synchronized(SingleTon.class){
                if(INSTANCE==null){
                    INSTANCE = new SingleTon();
                }
            }
        }
        return INSTANCE;
    }
}

DCL写法,双重检查锁写法,保证了线程安全,但是效率低了。

第四种

public enum SingleTon {
    INSTANCE;
    public void method(){
        System.out.println("嘿嘿");
    }
    public static void main(String[] args) {
        System.out.println(SingleTon.INSTANCE);
    }
}

枚举单例:避免反序列化,避免线程安全问题(一种很完美的写法),但是我们实际开发中,还是使用最合适的那种。

在实际开发中,一般是把单例交给Spring的bean来解决,我们很少直接写。

上一篇 下一篇

猜你喜欢

热点阅读