标签:
原链接http://www.ibm.com/developerworks/cn/java/j-lo-Singleton/
单例模式是一种对象创建模式,它用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例。Java里面实现的单例是一个虚拟机的范围,因为装载类的功能是虚拟机的,所以一个虚拟机在通过自己的 ClassLoad 装载实现单例类的时候就会创建一个类的实例。在 Java语言中,这样的行为能带来两大好处:
对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销;
由于 new 操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻 GC 压力,缩短 GC 停顿时间。
因此对于系统的关键组件和被频繁使用的对象,使用单例模式可以有效地改善系统的性能。单例模式的核心在于通过一个接口返回唯一的对象实例。首要的问题就是要把创建实例的权限收回来,让类自身来负责自己类的实例的创建工作,然后由这个类来提供外部可以访问这个类实例的方法
/** * 单例模式基本实现 */ public class Singleton { // 首先单例模式必须要有一个private访问级别的构造函数,才能确保单例不会在系统中其他代码内被实例化,其次,instance 成员变量和 // getInstance 方法必须是 static 的。 private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; } }
上述代码唯一的不足是无法对 instance 实例做延时加载,例如单例的创建过程很慢,而由于 instance 成员变量是 static 定义的,因此在 JVM加载单例类时,单例对象就会被建立,如果此时这个单例类在系统中还扮演其他角色,那么在任何使用这个单例类的地方都会初始化这个单例变量,而不管是否会被用到。
public class Singleton { private Singleton() { System.out.println("Singleton is create"); } private static Singleton instance = new Singleton(); public static Singleton getInsatnce() { return instance; } public static void createString() { System.out.println("createString in Singleton"); } public static void main(String[] args) { Singleton.createString(); } }
上述代码运行后的输出如
Singleton is create
createString in Singleton
可以看到,虽然此时并没有使用单例类,但它还是被创建出来,为了解决这类问题,需要引入延迟加载机制。
//延迟加载的单例模式 public class LazySingleton { private LazySingleton() { System.out.println("LazySingleton is create"); } private static LazySingleton instance = null; public static synchronized LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } public static void createString() { System.out.println("create String"); } public static void main(String[] args) { LazySingleton.createString(); } }
上述代码运行后的输出如
create String
上述代码首先对于静态成员变量 instance 初始化赋值 null,确保系统启动时没有额外的负载;其次,在 getInstance()工厂方法中,判断当前单例是否已经存在,若存在则返回,不存在则再建立单例。这里尤其要注意的是,getInstance() 方法必须是同步的,否则在多线程环境下,当线程1正新建单例时,完成赋值操作前,线程2可能判断instance为null,故线程2也将启动新建单例的程序,而导致多个实例被创建,故同步关键字是必须的。由于引入了同步关键字,导致多线程环境下耗时明显增加
标签:
原文地址:http://www.cnblogs.com/demacian/p/4500596.html