单例模式(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; 3 private Object clock = new Object(); 4 5 private Singleton2() { 6 } 7 8 public Singleton2 getInstance() { 9 if (instance == null) { 10 synchronized (clock) { 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,确保当变量 instance 被初始化成 Singleton2 实例时,多个线程正确的处理 instance 变量。该写法稍复杂,主要是为了性能考虑,不会在类加载的时候初始化对象,只要当使用的时候才初始化对象,提高性能。
第三种,比较简单的写法,在类被加载的时候就初始化了对象,所以在调用的时候直接返回这个变量就可以了,不存在线程不安全的问题,但是该对象可能存在不使用的问题,占用资源。
一种更好的写法,弥补饿汉式初始化以后不使用对象占用资源的问题,弥补懒汉式初始化过程中使用 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()方法没有任何线程锁定,因此其性能不会造成任何影响。
参考:http://blog.csdn.net/lovelion/article/details/7420888