`
caizi0413
  • 浏览: 6827 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

单例模式

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

(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() {
  }
}



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics