单例模式

198 阅读2分钟

课前准备:static

static 可以用来修饰:成员变量、成员方法、代码块享。

  • static 变量: 在内存中只有一个拷贝,JVM在加载类的过程中完成静态变量的内存分配且只分配一次内存,区别于实例变量(每次创建实例,都会分配一次内存)

  • static方法: 可以直接通过类名调用,static 方法中不能访问非静态成员方法和非静态成员变量。

  • static代码块:JVM加载类时会执行这些静态代码块,按照出现的先后顺序依次执行一次。

  • 1.饿汉模式

public class A {  
     private static A instance = new A();  
     private A (){
     }
     public static A getInstance() {  
     return instance;  
     }  
 }  

这种方式利用了上面描述的static 变量加载时机,在类加载时候就完成了初始化,但getInstance()这个方法显然没有懒加载效果(用到的时候在初始化)。

  • 2.懒汉模式(线程不安全)
public class A {  
      private static A instance;  
      private A (){
      }   
      public static A getInstance() {  
      if (instance == null) {  
          instance = new A();  
      }  
      return instance;  
      }  
 }  

这种设计模式满足了懒加载,且在整个内存中也只有一份变量,但是在多线程情况下有问题。

  • 3.懒汉模式(线程安全)
public class A {  
      private static A instance;  
      private A (){
      }
      public static synchronized A getInstance() {  
      if (instance == null) {  
          instance = new A();  
      }  
      return instance;  
      }  
 }  

通过加锁的方式保证了线程的安全性,但是每次调用getInstance方法都进行同步,开销较大。

  • 4.双重检查
public class A {  
      private volatile static A instance;  
      private A (){
      }   
      public static A getInstance() {  
      if (instance== null) {  
          synchronized (A.class) {  
          if (instance== null) {  
              instance= new A();  
          }  
         }  
     }  
     return singleton;  
     }  
 } 

但是由于JVM加载的乱序执行功能,所以也可能存在线程不安全的情况。

public class Singleton { 
    private Singleton(){
    }
      public static Singleton getInstance(){  
        return SingletonHolder.sInstance;  
    }  
    private static class SingletonHolder {  
        private static final Singleton sInstance = new Singleton();  
    }  
} 
  • 6.枚举类

  • 7.使用容器实现

public class A { 
private static Map<String, Object> objMap = new HashMap<String,Object>();
public static void registerService(String key, Object instance) {
if (!objMap.containsKey(key) ) {
objMap.put(key, instance) ;
}
}
public static ObjectgetService(String key) {
return objMap.get(key) ;
}
}

通过key、value 的形式保存、获取唯一的实例。