单例设计模式

(美少女的)单例设计模式

1、饿汉式写法

饿汉式单例是再类加载的时候就立刻初始化,并且创建单例对象。绝对的线程安全,在线程还没有出现以前就实例化了,不可能存在访问安全问题。

优点:没有加入锁、执行效率比较高,在用户体验上来说,比懒汉好

缺点:类加载的时候就初始化,不管用与不用都站着空间,浪费了内存,有可能创建对象后什么也不做。

spring 中的ioc容器ApplicationContext本身就是典型的饿汉式单例。 饿汉式适用于单例较少的

private static final SingleTon singleTon=new SingleTon();  //这里用关键字final 修饰是因为静态对象要在类加载的时候就new一个对象,如果不用的话 就要在静态代码块赋初值。也就是final的特性。
private SingleTon (){}
public static SingleTon getInstance(){
    return singleTon;
}

2、懒汉式写法

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

如果给getInstance()方法加上synchronized 后就会变成线程安全的方式。但是,假如有俩个线程,一个调用了这个方法,另一个再次调用这个方法就会有Running 变为monitor出现阻塞。直到第一个线程执行玩,第二个才恢复Running 状态继续调用getInstance()。这样的话cpu分配压力会增大,导致大量线程出现阻塞,从而导致程序运行性能大大减少。

3、双重检查锁的单例模式

是解决2的方式这种导致的问题

private static SingleTon singleTon=null;
private SingleTon(SingleTon.class){}
public static SingleTon getInstance(){
    if(singleTon==null){
    synchroized(){
       singleTon=new SingleTon()
         //1、分配内存给这个对象
         // 2、初始化对象
         // 3、将初始化好的对象和内存地址建立关联,赋值
         //4、用户初次访问
         
         cpu执行指令的时候会转化成jvm指令执行,会导致上述步骤重新排列。避免这个要在 private static SingleTon singleTon=null; 加上关键字volatile。即private volatile static SingleTon singleTon=null;
    }
    }
     
    return singleTon;
}

4、内部类的方式创建

这种形式兼顾了饿汉式的内存浪费,也兼顾了synchronrized性能问题。内部类一定要在方法调用之前初始化。内部类只有在调用的时候才会初始化。

private singleTon(){}
public static Singleton getInstance(){
return InnerSingleTon.SingleTon;
}
private static class InnerSingleTon(){
private static final SingleTon singleTon=new singleTon();
}

5、避免反射机制破坏单例

private singleTon(){
if(InnerSingleTon.SingleTon !=null){
throw new RuntimeException("不允许创建多个实例");//如果直接用4的方法,反射创建对象时 会有多个实例。加上这些 如果有反射创建会抛异常。
}
}
public static Singleton getInstance(){
return InnerSingleTon.SingleTon;
}
private static class InnerSingleTon(){
private static final SingleTon singleTon=new singleTon();
}

6、避免序列化破坏单例

public final static SeriableSingle INSTANCE=new SeriableSingle();
private SeriableSingle(){}
public static SeriableSingle getInstance(){
    return INSTANCE;
}

private Object readResolve(){ //重写这个方法,覆盖掉原来的。如果没有这个方法 在序列化的时候相当于创建了又一个新得对象,这个方法只是新创建的对象没有被返回
    return  INSTANCE;
}

7、注册式单例

推荐使用枚举:

public enum EnumSingleTon {
        INSTANECE;
        private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
    public  static EnumSingleTon getInstance(){
        return INSTANECE;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值