设计模式:单例模式

单例模式详解

设计模式:单例模式

1. 单例模式的应用

多用于程序只需要一个实例,通常是很消耗资源的类,例如:线程池,数据库,i/o,缓存,网络请求等,由于比较消耗资源,所以没必要创建多个实例。

2.单例模式举例

  • 饿汉式

 public class SingletionStarving {

 private static final SingletionStarving mInstance = new SingletionStarving();

 private SingletionStarving() {

 }

 public static SingletionStarving getInstance() {
     return mInstance;
 }
}

1、构造函数用private修饰,外部无法访问
2、声明静态对象时就初始化
3、static关键字修饰,静态变量,存储在内存中,只有一份数据。
4、final关键字,只初始化一次,所以mInstance实例只有一个。

  • 懒汉式
 
  public class SingletionSlacker {

   private static SingletionSlacker mInstance;

   private  SingletionSlacker() {}

   public static synchronized SingletionSlacker getInstance() {
       if (mInstance == null) {
           mInstance = new SingletionSlacker();
       }
       return mInstance;
      }
 }

1、构造函数用private修饰,外部无法访问
2、使用的时候即调用getInstance的时候才初始化
3、static关键字修饰,静态变量,存储在内存中,只有一份数据。
4、synchronized线程安全,多线程情况下单例的唯一性
5、缺点:没次调用getInstance都会同步一次,浪费资源

  • DCL式(Double Check Lock)

public class SingletionDLC {

    private static SingletionDLC mInstance;

    private SingletionDLC() {}

    public static SingletionDLC getmInstance() {
        if (mInstance == null) {
            synchronized (SingletionDLC.class) {
                if (mInstance == null) {
                    mInstance = new SingletionDLC();
                }
            }
        }
        return mInstance;
    }
}

//在饿汉式2层判空
1、构造函数用private修饰,外部无法访问
2、使用的时候即调用getInstance的时候才初始化
3、static关键字修饰,静态变量,存储在内存中,只有一份数据
4、synchronized线程安全,多线程情况下单例的唯一性
5、两次判断空,避免多次同步(synchronized)
缺点
private static SingletionDLC mInstance;
private SingletionDLC() {}
public static SingletionDLC getmInstance() {}
由于jvm特性,允许乱序执行,上面三句代码顺序不定,那么就可能出现DCL失效的问题。
步骤一、倘若A线程执行getmInstance(),还没执行构造方法SingletionDLC()
步骤二、此时B线程调用getmInstance()。因为A已经执行getmInstance(),所以mInstance不为空就直接获取。
步骤三、由于B直接获取,而真实情况是A线程构造方法还未执行,所以mInstance就为空了。
虽然此情况发生概率较小,但也是一种情况。为了解决这种情况,java1.6开始加入volatile关键字
private volatile static SingletionDLC mInstance;

public class SingletionDLC {

    private volatile static SingletionDLC mInstance;

    private SingletionDLC() {}

    public static SingletionDLC getmInstance() {
        if (mInstance == null) {
            synchronized (SingletionDLC.class) {
                if (mInstance == null) {
                    mInstance = new SingletionDLC();
                }
            }
        }
        return mInstance;
    }
}
  • 静态内部类方式
public class SingletionInternalClass {

    private SingletionInternalClass() {}

    public static SingletionInternalClass getInstance() {
        return SingletionInternalClassHolder.instance;
    }

    private static class SingletionInternalClassHolder {
        private static final SingletionInternalClass instance = new SingletionInternalClass();
    }
}
//推荐用这种模式,同时也能保证线程的安全,利用率也很高,缺点是第一次比较慢
  • 枚举类型
public enum  SingletionEmum {
   INSTANCE;
}
//这种模式简单,代码少,同时也达到线程安全,但是在内存中会有2份内存的开销
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值