java 单例模式

1. 饿汉式: 类静态变量,利用类的初始化,jvm 中一个class 只会初始化一次 

public class A{
    public static final A a= new A();
}

 

2. 懒汉式

public class A{
    private static A a;
    public synchronized static A getIns(){
       if(a==null){
             a = new A();
        }      
        return a;
    }          
}

  缺点: 对方法同步,效率低,每次进入方法都需要同步,其实只是第一次进入需要同步控制,当有值时就没有必要了。

改进1: 只对第一次a为null 的时候加同步

public class A{
        private static A a;
        public static A getIns(){
            if(a==null){
                  synchronized(A.class){
                      if(a==null) a = new A();
                  }
              }
              return a;
        }
}    

  缺点:java 重排序问题 , a=new A();  虽是一句,但在jvm是三步

  1.分配内存空间 2. 初始化对象 3. 将a 指向刚才的内存地址  。  重排序可能导致第二步在最后。 

       假设线程一 执行完成不在1 ,3  。 此时线程二判断a 此时不为null 就返回了。 这时a并未初始化。(但是应该没有哪个业务会这么快的访问前两次getIns).

  优化: 避免重排序,使用volatile 修饰,但是volatile只能保证可见性,不能控制并发,通常用于修饰作为开关状态的变量(true/false) ,不

      试用有多种状态的,如int i=0,然后累加。 

改进二: 依然利用类的初始化,使用内部静态类

public class A{
    public static class B{
       public static final A a= new A();
   }
   public static A getIns(){
          return B.a;
   }
}

 

posted on 2020-04-03 11:26  远方的人  阅读(125)  评论(0编辑  收藏  举报

导航