单例模式以及实现方式

  1. 定义
    一个类只有一个实例,并且只有一个全局获取入口
  2. 使用场景
    某个实例对象频繁被访问
    某个实例占用的资源较多
  3. 实现方式
    3.1 懒汉模式(线程不安全)
    public class Singleton{ private static Singleton singleton;//私有静态变量 private Singleton(){};//私有构造方法 //全局静态访问入口 public static Singleton getSingleton(){ if(singleton==null){ singleton=new Singleton(); }return singleton; } }

这样可能会出现多线程安全问题
3.2 懒汉模式(线程安全)
public class Singleton{
private static Singleton singleton;//私有静态变量
private Singleton(){};//私有构造方法
//全局静态访问入口
public static synchronized Singleton getSingleton(){
If(singleton==null){
Singleton=new Singleton();
}return singleton; } }
用锁会造成资源极大浪费
3.3 饿汉模式(线程安全)
public class Singleton{
private static Singleton singleton=new Singleton();//私有静态变量
private Singleton(){};//私有构造方法
//全局静态访问入口
Public static Singleton getSingleton(){
return singleton;
}
}
在声明私有静态变量时就实例化了类,没有线程同步问题,但会有启动问题,即会造成加载慢,若数量太多会雪崩。
3.4 DCL模式(Double CheckLock)
public class Singleton{
private static Singleton singleton;//私有静态内部变量
private Singleton(){};//私有构造方法
//全局静态访问入口
Public static synchronized Singleton getSingleton(){
If(singletonnull){
Synchronized(Singleton.class){
If(singleton
null){
Singleton=new Singleton();
}
}
}return singleton;
}
}
懒加载终极版:两层判断,第一层避免不必要的同步
第二层判断是否为null
可能会出现DCL失效
Singleton=new Singleton();这句话执行的时候,会进行下列三个过程

  1. 分配内存
  2. 初始化构造函数和成员变量
  3. 将对象指向分配空间
    由于JMM(Java Memory Model)的规定,可能会出现1-2-3 1-3-2两种情况
    而线程A进行到1-3时,被线程B抢走就会出现错误
    解决方法
    private volatile static Singleton singleton;
    3.5 静态内部类模式
    public class Singleton{
    private Singleton(){};//私有构造方法
    //全局静态访问入口
    Public static Singleton getSingleton(){
    return SingletonHolder.singleton;
    }
    private static class SingletonHolder{
    private final static Singleton singleton=new Singleton();
    }
    }
    第一次加载Singleton类不会加载内部类,调用才会加载
    没有线程、实例问题,又延时了加载
    目前最为推荐的方式
    3.6 枚举模式
    public enum SingletonEnum{
    INSTANCE;
    }
    简单粗暴,且没有线程问题,并且避免了序列化和反射攻击
    缺点:虽然很强但会损失类的一些特性,也没有延时加载
    除了枚举其他模式在实现Serializable接口后,反序列化时单例会被破坏,所以要重写readResolve()方法
    Private Object readResolve() throws ObjectStreamException{
    Return INSTANCE;
    }
    3.7 使用容器实现单例模式
    public class SingletonManger{
    private static Map<String,Object> objectMap=
    new HashMap<String,Object>();
    private SingletonManger(){};//私有构造方法
    Public static void registerService(String key,Object singleton){
    If(!objectMap.containsKey(key)){
    objectMap.put(key,singleton);
    }
    } Public static Object getObjectService(String key){
    Return objectMap.get(key);
    }
    }
    将多个单例对象注入HashMap中进行统一管理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值