单例模式

以下代码整理别人的,加上自己的认识,做些注释,当是笔记。

(1)第一种方式:通过final static 关键字直接让类加载时就初始化,简称恶汉式
public class SingletonClass {
  private static final SingletonClass instance = new SingletonClass();
  public static SingletonClass getInstance() {
  return instance;
  }
  private SingletonClass() {
  }
}

因为如上代码,类一加载就初始化了,如果类没有用到无缘消耗了资源。
所以提出延长初始化的概念(lazy loaded),即需要时再初始化。
(2)第二种方式:懒汉式,使用synchronized关键字同步方法体
public class SingletonClass {
  private static SingletonClass instance = null;
  public synchronized static SingletonClass getInstance() {
   if (instance == null) {
   instance = new SingletonClass();
  }
  return instance;
  }
  private SingletonClass() {
  }
}

由于懒汉式只需第一次判断即可,如果此类需要初始化资源消耗过多时,无疑会造成性能问题,所以提出
(3)所谓的double-checked方式,懒汉式升级版
 public class SingletonClass {
  private static SingletonClass instance = null;
  public static SingletonClass getInstance() {
  if (instance == null) {//首先判断,提高性能,因为只有第一次才需要synchronized
   synchronized (SingletonClass.class) {
   if (instance == null) {//保证多线程条件下单例唯一
   instance = new SingletonClass();
   }
   }
  }
  return instance;
  }
  private SingletonClass() {
  }
}

但JAVA语言中却不能使用此double-checked模式,因为
语言在编译时需要编译优化,即在不改变原来语义的情况下,通过调整语句顺序,来让程序运行的更快。这个过程成为reorder。
JVM只是一个标准,并不是实现。JVM中并没有规定有关编译器优化的内容,也就是说,JVM实现可以自由的进行编译器优化。
所以,JVM就存在两种初始化对象的模型:
开辟内存空间,调用构造方法,然后指针指向内存。
开辟内存空间,指针指向内存,然后调用构造方法。
针对第二种情况,加入线程B现在调用getInstance方法,而线程A刚好在创建对象,而此时线程B判断instance不为null,事实上null还没真正初始化成功,所以出错。

(3)解决方法:
//通过volatile关键字——被volatile修饰的写变量不能和之前的读写代码调整,读变量不能和之后的读写代码调整,但需要JDK1.5以上版本支持
public class SingletonClass {
  private volatile static SingletonClass instance = null;
  public static SingletonClass getInstance() {
  if (instance == null) {
  synchronized (SingletonClass.class) {
  if(instance == null) {
  instance = new SingletonClass();
  }
  }
  }
  return instance;
  }
  private SingletonClass() {
  }
}
//静态内部类处理,事实上是单例第一种方式的修改。(第一,起到了延迟初始化的作用;第二,优化了synchronized性能)
public class SingletonClass {
  private static class SingletonClassInstance {
  private static final SingletonClass instance = new SingletonClass();
  }
  public static SingletonClass getInstance() {
  return SingletonClassInstance.instance;
  }
  private SingletonClass() {
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值