序言

单例(Singleton) 是指那些仅仅被初始化一次的类。
如这样

  1. public class Elvis {
  2. public static final Elvis INSTANCE = new Elvis();
  3. private Elvis() {
  4. }
  5. public void leaveTheBuilding(){
  6. }
  7. }

私有的构造器在类被加载的时候,只运行了一次,用来实例化 final 域的 INSTANCE 。(不推荐有安全因素),除此之外还有几种常见的构建单例的方式。

饿汉模式

  1. public class Elvis {
  2. private static final Elvis INSTANCE = new Elvis();
  3. public static Elvis getINSTANCE() {
  4. return INSTANCE;
  5. }
  6. private Elvis() {
  7. }
  8. public void leaveTheBuilding() {
  9. }
  10. }

还可以加入一个 getINSTANCE() 方法,这种方式呢就是之前所说的静态工厂构造, 使用 private static final 则使 INSTANCE 在初始化的时候具有绝对的线程安全。

懒汉的双重加锁机制

  1. public class Elvis {
  2. private volatile static Elvis INSTANCE;
  3. public static Elvis getINSTANCE() {
  4. if (INSTANCE == null) {
  5. synchronized (Elvis.class) {
  6. if (INSTANCE == null) {
  7. INSTANCE = new Elvis();
  8. }
  9. }
  10. }
  11. return INSTANCE;
  12. }
  13. private Elvis() {
  14. }
  15. public void leaveTheBuilding() {
  16. }
  17. }

volatile 关键字确保,当 INSTANCE 变量被初始化成Elvis实例时,多个线程正确地处理INSTANCE 变量

静态内部类

  1. public class Elvis {
  2. private static class LazyHolder {
  3. private static final Elvis INSTANCE = new Elvis();
  4. }
  5. public static Elvis getINSTANCE() {
  6. return LazyHolder.INSTANCE;
  7. }
  8. private Elvis() {
  9. }
  10. public void leaveTheBuilding() {
  11. }
  12. }

序列化问题

上述所有构建单例的方式都有 序列化的问题,因此在实现 Serializable 的同时呢还有加入一个 readResolve方法,否则每一次反序列化都会产生一个新的实例。

  1. private Object readResolve(){
  2. return INSTANCE;
  3. }

枚举单例

枚举单例就厉害了,无偿提供了序列化机制,绝对防止多次实例化!!!

  1. public class Elvis {
  2. enum SingletonEnum {
  3. INSTANCE;
  4. private Elvis elvis;
  5. SingletonEnum() {
  6. elvis = new Elvis();
  7. }
  8. public Elvis getInstnce() {
  9. return elvis;
  10. }
  11. }
  12. public static Elvis getINSTANCE() {
  13. return SingletonEnum.INSTANCE.getInstnce();
  14. }
  15. private Elvis() {
  16. }
  17. public void leaveTheBuilding() {
  18. }
  19. }

单例枚举已经成为实现单例的最佳方法。