单例模式

单例模式:

原理:私有化构造方法,通过静态方法获取一个唯一的实例。(获取过程中必须保证线程安全、防止反序列化导致重新生成对象等问题。)

饿汉式:

public class SingleTon {
    //在类初始化时直接new对象
    private static SingleTon instance = new SingleTon();
    private SingleTon(){}

    public static SingleTon getInstance(){
        return instance;
    }
}

懒汉式:

public class SingleTon {

    private static SingleTon instance;
    private SingleTon(){}

    //同步方法获取唯一实例。缺点:每次getInstance时都会同步,浪费资源。
    public static synchronized SingleTon getInstance(){
        //判断对象是否存在
        if (instance == null){
            instance = new SingleTon();
        }
        return instance;
    }

    //去掉synchronized。缺点:不能保证单例的唯一性。(但android中并发情况少)
    public static SingleTon getInstance(){
        if (instance == null){
            instance = new SingleTon();
        }
        return instance;
    }
}

Double Check Lock(DCL双重判断校验):


public class SingleTon {
    private static SingleTon instance;
    private SingleTon() {}

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

/**
     * DCL失效:
     * 
     * SingleTon instance = new SingleTon() 这句代码最终会编译成多条汇编指令。
     * 大致做了3件事:
     * 1、给SingleTon的实例分配内存;
     * 2、调用SingleTon()的构造函数,初始化成员字段;
     * 3、将instance对象指向分配的内存空间(此时instance就不再是null)
     * 但是,由于Java编译器允许处理器乱序执行,以及JDK1.5之前JMM(Java Memory Model,即Java内存模型)
     * 中的Cache、寄存器到主内存回写顺序的规定,上面的第二和第三顺序无法保证。
     * 也就是说,执行顺序可能是1-2-3,也可能是1-3-2。
     * 如果是1-3-2顺序执行,就可能出现如下情况:
     * 程序执行到3完毕,2还没来得及执行,CPU资源切换到线程B,由于instance已经不是null了,
     * 所以线程B会直接取走instance,而上面的步骤2将不会得到执行。
     * 在使用时就会出错,就就是DCL失效问题。
     * 而且这种难以追踪难以重现的问题可能会隐藏很久。
     *    
     * 
     * 在JDK1.5之后,调整了JVM,具体化了volatile关键字。
     * 因此JDK1.5之后的版本,只需要将instance的定义改成
     * private volatile static SingleTon instance = null
     * 就可以保证对象每次都是从主内存中读取,
     * DCL失效问题解决。
     * 
     * 不足:volatile或多或少会影响到性能
     * 
     * DCL的优点:资源利用率高,效率高。绝大多数场景下能保证单例对象的唯一性。
     * 缺点:第一次加载反应稍慢,小概率由于java内存模型原因失败。
     */

静态单例:

//推荐使用
public class SingleTon {
    private SingleTon(){}
    public static SingleTon getInstance(){
        return SingletonHolder.instance;
    }

    /**
     * 静态内部类
     *
     * 既保证了线程安全,又保证了对象的唯一性
     */
    private static class SingletonHolder{
        private static final SingleTon instance = new SingleTon();
    }
}

枚举单例:

//枚举比static占内存多很多
public enum SingleTon {
    INSTANCE
}

容器单例:

public class SingletonManager {

    private static Map<String, Object> objMap = new HashMap<>();

    private SingletonManager(){}

    public static void registerService(String key, Object instance){
        if (!objMap.containsKey(key)){
            objMap.put(key, instance);
        }
    }

    public static Object getService(String key){
        return objMap.get(key);
    }
}

&&
Android Studio 可直接创建单例,以上内容,可权当了解。
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值