单例模式

趁着找工作的间隙给自己「充充电」。最近在看「Andriod设计模式」,在这之前对单例的理解比较浅显:知道单例模式可以保证一个场景有且只有一个对象,避免产生多个对象消耗资源;知道单例模式如果传context-activity参数容易引起内存泄漏,所以尽量使用context-application替代context-activity。但是真心不知道单例模式竟然有五花八门的写法:饿汉模式、懒汉模式、Double Check Lock 模式、静态内部类模式、枚举模式、容器模式。下面对这几种模式一一介绍,并分析其优缺点。

懒汉模式

public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static  Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

缺点:这种模式多线程下无法保证对象唯一性

懒汉模式(同步)

public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static synchronized  Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

这个跟上面的区别是添加synchronized关键字,保证多线程情况下可以对象的唯一性,但是致命的缺点是:每次getInstance的时候都要同步,造成不必要的同步开销(99%情况下不需要同步),所以不建议使用。

饿汉模式

   public class Singleton {
        private static Singleton instance=new Singleton();
        private Singleton() {
        }
        public static  Singleton getInstance() {
            return instance;
        }
    }

优点是:写起来比较简单,而且不存在多线程同步问题,避免了synchronized所造成的性能问题;
缺点是:初始化类的时候就需要构造实例,(即便你还没有用到这个实例),因此在某些特定条件下会耗费内存。

Double Check Lock

public class Singleton {
    private static Singleton mInstance = null;
    private Singleton() {
    }
    public static Singleton getInstance() {
        if (mInstance == null)
            synchronized (Singleton.class) {
                if (mInstance != null) {
                    mInstance = new Singleton();
                }
            }
        return mInstance;
    }
}

优点:资源利用率高,第一次执行getInstance时,对象才会被实例化,效率高。
缺点:第一次加载反应慢,在高并发或者低于JDK6版本下,不能保证对象唯一性。

静态模式推荐使用

public class Singleton {
    private Singleton() {
    }
    public static Singleton getInstance() { 
        return SingletonHolder.sInstance;
    }
    private static class  SingletonHolder{
        private static  final  Singleton sInstance=new Singleton();
    }
}

不仅可以保证线程安全,也能保证单例对象的唯一性,第一次加载Singleton不会初始化sInstance,第一次调用getInstance方法时才会初始话sInstance—推荐使用。

枚举单例

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
} 

这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,但是这种方法对单价比较陌生,实际工作中很少看到有人这么写。

使用容器

public class SingleManager {
    private static Map<String, Object> objectMap = new HashMap<String, Object>();
    private SingleManager () {
    }
    public static void registerInstance(String key, Object mInstance) {
        if (!objectMap.containsKey(key)) {
            objectMap.put(key, mInstance);
        }
    }
    public static Object getInstance(String key) {
        return objectMap.get(key);
    }
}

可以管理多种类型的单例(通过key方便获取),降低用户的使用成本。

总结
核心原来都是构造函数私有化,通过静态方法获取唯一实例,在获取的过程中保证线程安全、防止反序列化导致重新生成实例对象(高并发环境、JDK低版本、资源消耗)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值