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; } }