Java——单例模式

来源:互联网 发布:商品条码数据库下载 编辑:程序博客网 时间:2024/04/27 11:44

定义

单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

饿汉式单例

/* * 饿汉式单例 */public class Singleton {    private static final Singleton instance = new Singleton();    //禁止类的外部直接使用new来创建对象    private Singleton() {    }    public static Singleton getInstance() {        return instance;    }}

懒汉式单例

class LazySingleton {       private volatile static LazySingleton instance = null;       private LazySingleton() { }       public static LazySingleton getInstance() {           //第一重判断,提高并发性能          if (instance == null) {              //锁定代码块              synchronized (LazySingleton.class) {                  //第二重判断,防止多线程产生多个实例                  if (instance == null) {                      instance = new LazySingleton(); //创建单例实例                  }              }          }          return instance;       }  }

饿汉式与懒汉式比较

饿汉式单例类在类被加载时就将自己实例化,它的优点在于无须考虑多线程访问问题,可以确保实例的唯一性;从调用速度和反应时间角度来讲,由于单例对象一开始就得以创建,因此要优于懒汉式单例。但是无论系统在运行时是否需要使用该单例对象,由于在类加载时该对象就需要创建,因此从资源利用效率角度来讲,饿汉式单例不及懒汉式单例,而且在系统加载时由于需要创建饿汉式单例对象,加载时间可能会比较长。

懒汉式单例类在第一次使用时创建,无须一直占用系统资源,实现了延迟加载,但是必须处理好多个线程同时访问的问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的机率变得较大,需要通过双重检查锁定等机制进行控制,这将导致系统性能受到一定影响。

一种更好的选择

饿汉式单例类不能实现延迟加载,不管将来用不用始终占据内存;懒汉式单例类线程安全控制烦琐,而且性能受影响。下面这种方式既可以实现延迟加载,又可以保证线程安全,不影响系统性能。

//Initialization on Demand Holder  class Singleton {      private Singleton() {      }      private static class HolderClass {          private final static Singleton instance = new Singleton();      }      public static Singleton getInstance() {          return HolderClass.instance;      }      public static void main(String args[]) {          Singleton s1, s2;           s1 = Singleton.getInstance();          s2 = Singleton.getInstance();          System.out.println(s1==s2);      }  }

由于静态单例对象没有作为Singleton的成员变量直接实例化,因此类加载时不会实例化Singleton,第一次调用getInstance()时将加载内部类HolderClass,在该内部类中定义了一个static类型的变量instance,此时会首先初始化这个成员变量,由Java虚拟机来保证其线程安全性,确保该成员变量只能初始化一次。由于getInstance()方法没有任何线程锁定,因此其性能不会造成任何影响。这种方式利用了classloder的机制来保证初始化instance时只有一个线程。



[参考资料]
设计模式Java版

1 0
原创粉丝点击