• Singleton
  • 确保只有一个实例
    • 大多有资源管理器的功能
    • 反射机制会使所有单例失效:私有构造方法可以被访问
  • 应用
    • 线程池
    • 缓存
    • 日志对象
    • 对话框
    • 打印机
    • 显卡驱动程序
  • 饿汉
  • public class Singleton {
        public static Singleton instance = new Singleton();
        private Singleton(){}
        public static Singleton getInstance(){
            return instance;
        }
    }
  • 懒汉式
  • public class Singleton {
        private static Singleton single=null;
        private Singleton() {}
        public synchronized  static Singleton getInstance() {
            if (single == null) {
                single = new Singleton();
            }
            return single;
        }
    }
  • 懒汉,双重检测(DCL)
    • 解决问题并发创建问题。在不同jvm或多核cpu上,有无序写入bug。
    • 解决bug: 1 直接创建static属性, 2 get方法修饰synchronized
    • public class Singleton {
          private static volatile Singleton singleton = null;
              # volatile: t1编译singleton = new Singleton()时重排序把没初始化对象赋值给singleton时, t2判断singleton为null。
          private Singleton(){}
          public static Singleton getInstance(){
              if (singleton == null) {
                  // t1,t2并发进入
                  synchronized (Singleton.class) {
                      // t1释放后,t2进入
                      if (singleton == null) {
                          singleton = new Singleton();
                      }
                  }
              }
              return singleton;
          }
      }
  • map注册
    • 学Spring,将类名注册
    • public class Singleton {
          private static Map<String,Singleton> map = new HashMap<String,Singleton>();
          static{
              Singleton single = new Singleton();
              map.put(single.getClass().getName(), single);
          }
          protected Singleton(){}
          public static Singleton getInstance(String name) {
              if(name == null) {
                  name = Singleton.class.getName();
              }
              if(map.get(name) == null) {
                  map.put(name, (Singleton) Class.forName(name).newInstance());
              }
              return map.get(name);
          }
      }