设计模式二:单例模式

  • 掌握单例模式的应用场景。
  • 掌握IDEA环境下的多线程调试方式。
  • 掌握保证线程安全的单例模式策略。
  • 掌握反射暴力攻击单例解决方案及原理分析。
  • 序列化破坏单例的原理及解决方案。
  • 掌握常见的单例模式写法。
  • 掌握原型模式的应用场景及常用写法。

任何情况下只有一个实例,提供全局一个访问点。

ServletContext、ServletConfig、BeanFactory、ApplicationContext、DBPool

饿汉式单例:

在初始话的时候直接new出来了,不需要在调用的时候去new,这样就避免了线程安全的问题。

优点:1.线程绝对安全。2.执行效率高。在类加载的时候就初始化了。

缺点:1.浪费类型空间,占用内存。占着空间,浪费资源。

public class Hungry {

    private Hungry(){}
    private static final Hungry hungry = new Hungry();

    public static Hungry getInstance(){
        return  hungry;
    }

}

懒汉式:
在需要的时候才会去创建。

优点:1.占用空间小

缺点:1.需要自己解决线程安全问题。

特点:在外部类被调用的时候内部类才会被加载内部类一定是要在方法调用之前初始化巧妙地避免了线程安全问题
这种形式兼顾饿汉式的内存浪费,也兼顾synchronized性能问题,完美地屏蔽了这两个缺点。
史上最牛B的单例模式的实现方式

public class LazyOne{
    
    private static LazyOne lazyOne=null;
    private LazyOne(){}
    
    public static LazyOne getInstance(){
        //线程不安全
        if(lazyOne==null){
            lazyOne=new LazyOne();
        }
        return lazyOne;
    }
}



public class LazyTwo{
    
    private static LazyTwo lazyTwo=null;
    private LazyTwo(){}
    
    public static synchronized LazyTwo getInstance(){
        //线程安全,执行效率低
        if(lazyTwo==null){
            lazyTwo=new LazyTwo;
        }
        return lazyTwo;
    }
}


public class LazyThree{
    
    private static LazyThree lazythree=null;
    private LazyThree(){}
    
    public static  LazyThree getInstance(){
        //线程安全,执行效率可以
       if(lazythree==null){
            synchronized(LazyThree.class){
                if(lazythree==null){
                  lazythree=new LazyThree();
                }
            }
        }
        return lazythree;
    } 
}



public class LazyFour{
    
    private static LazyFour lazyFour=null;
    private LazyFour(){
        //防止反射入侵单例
        if(lazyFour!=null){
            throw new RunTimeException("单例被入侵");
        }
        
    }
    
    public static  LazyTwo getInstance(){
        lazyFour=LazyHandle.lazyFour;
    } 
    
    private static class LazyHandle{
        static LazyFour lazyFour=new LazyFour();
    }
    
}

注册试:

public class ReginsterSingle {

    //HashMap 变成ConcurrentHashmap就是线程安全的
    private Map<String,Object> registerMap=new HashMap<>();

    private ReginsterSingle(){}

    public ReginsterSingle getInstance(String name){

        if(name!=null){
            name = ReginsterSingle.class.getName();
        }
        if (registerMap.get(name)==null){
            registerMap.put(name, new ReginsterSingle());
        }
        return (ReginsterSingle)registerMap.get(name);
    }

}
//枚举式
public enum RegiterEnum {
    INSTANCE,BLACK,WHITE;
    public void getInstance(){}
}

序列化和反序列化:

  1. 把对象转换为字节序列的过程称为对象的序列化。
  2. 把字节序列恢复为对象的过程称为对象的反序列化。

对象的序列化主要有两种用途:

  1. 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中。
  2. 在网络上传送对象的字节序列;

实现readResolve方法可以防止反序列化。

   public  final static Seriable INSTANCE = new Seriable();
    private Seriable(){}

    public static  Seriable getInstance(){
        return INSTANCE;
    }

    private  Object readResolve(){
        return  INSTANCE;
    }

关注公众号,精彩继续
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值