Android单例模式-饿汉模式-DCL模式-内部静态类-双重检查锁定模式-懒汉模式

Android单例模式-饿汉模式-DCL模式-内部静态类-双重检查锁定模式-懒汉模式

懒汉模式

/**
 * 懒汉模式
 * 缺点:由于未加锁,线程不安全。在多线程并发请求的情况下,可能会同时创建多个对象实例
 */
public class SluggardSingleton {

    private static SluggardSingleton mInstance= new SluggardSingleton();

    private SluggardSingleton(){
        Log.d(MainActivity.TAG, "SluggardSingleton: 初始化,构造函数用private修饰,避免了类在外部被实例化");

    }
    public static SluggardSingleton getInstance(){
        Log.d(MainActivity.TAG, "SluggardSingleton: 返回mInstance");
        return mInstance;
    }
}


饿汉模式


/**
 * 饿汉模式
 * 声明静态对象时才初始化,且加锁
 * 缺点:对类加了锁,保证了实例的唯一性,但是每次获取实例都需要线程同步一次,浪费资源
 */
public class StarvingSingleton {
    private static StarvingSingleton mInstance;

    private StarvingSingleton (){
        Log.d(MainActivity.TAG, "StarvingSingleton: 初始化,构造函数用private修饰,避免了类在外部被实例化");
    }

    public static synchronized StarvingSingleton getInstance(){
        if(null == mInstance){
            Log.d(MainActivity.TAG, "StarvingSingleton: 检查 check mInstance为空,进行初始化");
            mInstance = new StarvingSingleton();
        }else {
            Log.d(MainActivity.TAG, "StarvingSingleton: mInstance已存在,直接返回");
        }
        return mInstance;
    }

}


DCL模式


/**
 * DCL模式, Double Check Lock
 * 调用getInstance()的时候才进行初始化
 * 缺点:
 * 由于jvm特性,允许乱序执行,上面三句代码顺序不定,那么就可能出现DCL失效的问题。
 * 步骤一、倘若A线程执行getInstance(),DCLSingleton()
 * 步骤二、倘若A线程执行getInstance()。因为A已经执行getInstance(),所以mInstance不为空就直接获取。
 * 步骤三、由于B直接获取,而真实情况是A线程构造方法还未执行,所以mInstance就为空了。
 * 虽然此情况发生概率较小,但也是一种情况。为了解决这种情况,java1.6开始加入volatile关键字
 *
 */
public class DCLSingleton {
    private static DCLSingleton mInstance;

    private DCLSingleton(){
        Log.d(MainActivity.TAG, "DCLSingleton: 初始化,构造函数用private修饰,避免了类在外部被实例化");
    }
    public static DCLSingleton getInstance(){
        if(null == mInstance){
            Log.d(MainActivity.TAG, "DCLSingleton: 最外部 check mInstance 为空,对类进行加锁");
            synchronized (DCLSingleton.class){ //synchronized修饰代码块,对该类进行加锁,那么同一时间该类只能被访问一次,保证线程安全
                if(null == mInstance){
                    Log.d(MainActivity.TAG, "DCLSingleton: 再次检查 check mInstance 为空,初始化");
                    mInstance = new DCLSingleton();
                }
            }
        }else {
            Log.d(MainActivity.TAG, "DCLSingleton: mInstance已存在,直接返回");
        }
        return mInstance;
    }

}


DCL + Volatile


/**
 * DCL Volatile模式, Double Check Lock
 * 调用getInstance()的时候才进行初始化
 * 缺点:
 * volatile避免了DCL会失效的情况,但是会消耗一些性能,所以DCL最佳写法
 * 虽然volatile让DCL方式完美,但是没有volatile关键字的写法基本能满足绝大部分情况。
 * 除非你要运行在高并发。
 */
public class DCLVolatileSingleton {
    private static volatile DCLVolatileSingleton mInstance;

    private DCLVolatileSingleton(){
        Log.d(MainActivity.TAG, "DCLVolatileSingleton: 初始化,构造函数用private修饰,避免了类在外部被实例化");
    }
    public static DCLVolatileSingleton getInstance(){
        if(null == mInstance){
            Log.d(MainActivity.TAG, "DCLVolatileSingleton: 最外部 check mInstance 为空,对类进行加锁");
            synchronized (DCLVolatileSingleton.class){ //synchronized修饰代码块,对该类进行加锁,那么同一时间该类只能被访问一次,保证线程安全
                if(null == mInstance){
                    Log.d(MainActivity.TAG, "DCLVolatileSingleton: 再次检查 check mInstance 为空,初始化");
                    mInstance = new DCLVolatileSingleton();
                }
            }
        }else {
            Log.d(MainActivity.TAG, "DCLVolatileSingleton: mInstance已存在,直接返回");
        }
        return mInstance;
    }

}


内部静态类


/**
 * 内部静态类
 * 调用getInstance()的时候才进行初始化
 * 优点:既实现了线程安全,又避免了同步带来的性能影响。
 * static final 是一个静态常量,存储在内存中的常量区,在new之前会看常量里面是否有这个值,如果有,就不再执行new操作了
 *  
 * 这种方式采用了类装在的机制来保证初始化实例时只有一个线程,
 * 静态内部类方式在Singleton类被装在时并不会立即实例化,而是在需要实例化时,
 * 调用getInstance()方法,才会装载SingletonInstance类,
 * 从而完成Singleton的实例化,类的静态属性只会在第一次加载类的时候初始化,
 * 所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
 * 避免了线程不安全,利用静态内部类特点实现延迟加载,效率高。
 *
 */

public class InternalClassSingleton {
    private InternalClassSingleton (){
        Log.d(MainActivity.TAG, "InternalClassSingleton: 初始化,构造函数用private修饰,避免了类在外部被实例化");

    }

    public static InternalClassSingleton getInstance(){
        return InternalClassSingletonHolder.instance;
    }


    private static class InternalClassSingletonHolder {
        private static final InternalClassSingleton instance = new InternalClassSingleton();
    }
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值