您的位置:首页 > 移动开发 > Android开发

Android多种单例模式的使用

2016-01-13 23:00 525 查看
单例模式的简单定义:

单例模式是应用最广的模式之一,确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,应用在一些创建对象需要消耗较多资源的地方。

单例模式的实现方式,在这里讲解了5种:1.懒汉模式,2.Double CheckLock(DCL)实现单例,3.静态内部类,4.枚举单例,5.使用容器实现单例模式。

OK,现在我们来一一的看一下他们的实现方式分别是什么:

1、懒汉模式是申明一个静态变量,在用户第一次调用getInstance时进行初始化

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


这种懒汉模式每一次调用都需要进行同步,造成不必要的开销(一般不建议使用)

饿汉模式的话就在类加载的时候直接初始化 private static Singleton instance = new Singleton();

2、DCL实现单例,优点是能够在需要时才初始化,又能保证线程安全且单例对象初始化后调用getInstance不进行同步锁

public class Singleton{
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){   //主要为了避免不必要的同步
synchronized(Singleton.class){
if(instance == null){    //为了在空的情况下创建实例
instance = new Singleton();
}
}
}
return instance;
}
}


instance = new Singleton();的实际操作:

1.给Singleton分配内存,2调用Singleton的构造函数,初始化成员字段,3将instance对象指向分配的内存空间

但是Java编译器允许处理器乱序执行,已经JDK1.5之前JMM(Java Memory Model)中Cache,寄存器到主内存回写顺序的规定执行顺序可能是123,也可能是132,如果是132就会出现instance不是空,但是使用的时候会有问题,1.6开始已经作了调整,利用

Private volatile static Singleton instance = null;就可以保证安全性,但是会消耗一些性能

优点:资源资源利用率高,是使用最多的单利实现方式,可以满足绝大多数的单例,但是在一些高并发或者JDK1.6版本以下使用会有创建失败的可能性

3、静态内部类的单例模式,DCL存在一定的失效概率问题,所以我们可以使用以下代码来代替:

public class Singleton{
private Singleton(){}
public static Singleton getInstance(){
return SingletonHolder.sInstance;
}
/**
*静态内部类
*/
private static SingletonHolder{
private static final Singleton sInstance = new Singleton();
}
}


第一次加载Singleton时不会初始化sInstance,只有第一次调用getInstance的时候才会初始化,因此导致虚拟机加载SingletonHolder类,这种方式不仅能保证线程安全,也能保证唯一性和延迟加载,推荐使用

4、使用枚举类来完成单例模式

public enum SingletonEnum(){
INSTANCE;
public void doSomething(){
System.out.println("===");
}
}


反序列化:在上述的集中单例模式中,反序列化会导致对象的重新创建(即使构造方法是私有的也会),但是反序列化操作提供了一个很特别的函数readResolve(),这个方法可以控制对象的反序列化;

private Object readResolve() throws ObjectStreamException{
return sInstance;
}


但是,默认枚举类实例是线程安全的,并且在任何情况下它都是一个单例也不会受到反序列化的影响

5、使用容器实现单例模式的管理,这种模式重点在于对单例模式的管理

public class SingletonManager{
private static Map<String,Object> objMap = new HashMap<String,Object>();
private Singleton(){}
public static void registerService(String key, Object instance){
if(!objMap.containsKey(key)){
objMap.put(key,instance);
}
public static Object getService(String){}
return objMap.get(key);
}
}


在程序初始化的时候将多种单例类注入到统一的管理类中,再用key进行获取
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: