设计模式-单例模式(Singleton Pattren)(饿汉模式和懒汉模式)
单例模式(Singleton Pattren):确保一个类在整个应用中只有一个实例,并提供一个全局访问点。
实现要点:
1. 私有化构造方法
2. 类的实例在类初始化的时候创建
3. 提供一个类方法,返回值为类的实例,其他类调用该方法获取到该类的实例
1. 常规实现(线程不安全,不考虑多线程):
1 public class Singleton1 { 2 private static Singleton1 instance; 3 4 private Singleton1() { 5 6 } 7 8 public static Singleton1 getInstance() { 9 if (instance == null) { 10 instance = new Singleton1(); 11 } 12 return instance; 13 } 14 }
2. 线程安全懒加载实现(懒汉式):
1 public class Singleton2 { 2 private volatile static Singleton2 instance; 4 5 private Singleton2() { 6 } 7 8 public Singleton2 getInstance() { 9 if (instance == null) { 10 synchronized (Singleton2.class) { 11 if (instance == null) { 12 instance = new Singleton2(); 13 } 14 } 15 } 16 return instance; 17 } 18 }
3. 线程安全快速加载实现(饿汉式):
1 public class Singleton3 { 2 private static Singleton3 instance = new Singleton3(); 3 4 private Singleton3() { 5 } 6 7 public static Singleton3 getInstance() { 8 return instance; 9 } 10 }
三种实现方法中:
第一种,假如在单线程模式下,是可以的,不会出现多个实例的情况,但是在多线程的模式下是不安全的,可能会创建多个实例。
第二种,在方法内部进行了加锁操作,同时使用 volatile 修饰 instance,防止 Java 指令重排,确保当变量 instance 被初始化成 Singleton2 实例时,多个线程正确的处理 instance 变量。该写法只有在使用的时候才会初始化对象,可以提高性能。
第三种,比较简单的写法,在类被加载的时候就初始化了对象,所以在调用的时候直接返回这个变量就可以了,线程安全由 JVM 来确保,因为 JVM 加载的时候是单线程的。不存在线程不安全的问题,但是该对象在类加载进 JVM 的时候就初始化了,会占用资源。
一种更好的写法,弥补饿汉式初始化以后不使用对象占用资源的问题,弥补懒汉式初始化过程中使用 synchronized 影响性能的问题
1 public class Singleton4 { 2 3 private Singleton4() { 4 } 5 6 private static class Holder { 7 private static Singleton4 instance = new Singleton4(); 8 } 9 10 public static Singleton4 getInstance() { 11 return Holder.instance; 12 } 13 }
由于静态单例对象没有作为Singleton的成员变量直接实例化,因此类加载时不会实例化Singleton,第一次调用getInstance()时将加载内部类HolderClass,在该内部类中定义了一个static类型的变量instance,此时会首先初始化这个成员变量,由Java虚拟机来保证其线程安全性,确保该成员变量只能初始化一次。由于getInstance()方法没有任何线程锁定,因此其性能不会造成任何影响。
知识点: 可以写出三种单例模式,参考:《Effictive Java》单例模式的实现
参考:http://blog.csdn.net/lovelion/article/details/7420888