公开课Singleton1 {//不能延迟加载占用内存耗费资源 私有静态Singleton1 Singleton1=new Singleton1 (); 公共静态Singleton1 getSingleton1 () { 返回singleton1; } } >之前可以保证多个线程下唯一实例,getSingleton1方法性能较高,但是无法进行懒加载。
公开课Singleton2 {//延迟加载//多线程下不安全 私有静态Singleton2 singleton1=零; 公共Singleton2 getSingleton1 () { 如果(singleton1==null) { singleton1=new Singleton2 (); } 返回singleton1; } } >之前懒汉式解决了延迟加载和资源问题,但是多线程下存在线程不安全问题。
公开课Singleton3 {//延迟加载//多线程下不安全 私有静态Singleton3 singleton1=零;//解决延迟加载多线程安全问题,但存在读操作,加锁问题,线程排队,写操作只有一次获取时需要排队等候问题 公共同步Singleton3 getSingleton1 () { 如果(singleton1==null) { singleton1=new Singleton3 (); } 返回singleton1; }/* 等同方法前加锁 公共静态Singleton3 getSingleton1 () { 同步(Singleton3.class) { 如果(singleton1==null) { singleton1=new Singleton3 (); } } 返回singleton1; } */} >之前解决延迟加载多线程安全问题,但存在读操作,加锁问题,线程排队,写操作(创建对象)只有一次,但是获取时需要排队等候问题
公开课Singleton4 {//延迟加载 私有静态Singleton4 singleton1=零;//解决读操作多线程情况下排队获取问题,但是双重校验也存在一个问题,jvm重排序的问题下会存在空指针问题 公共静态Singleton4 getSingleton1 () { 如果(singleton1==null) { 同步(Singleton4.class) { 如果(singleton1==null) { singleton1=new Singleton4 (); } } } 返回singleton1; } } >之前解决读操作多线程情况下排队获取问题,但是双重校验也存在一个问题,jvm重排序的问题下会存在空指针问题
但存在一个问题,jvm指令重排序,jvm的即时编译器中存在指令重排序的优化。
1首先给singleton1分配内存
2 Singleton4执行构造函数开辟空间
3调用getSingleton1()方法创建对象
JVM的即时编译器中存在指令重排序的优化理想情况下jvm执行顺序是123也可能是132年,13在创建完对象后,再执行2返回零,此时就是空指针了。
挥发性关键字禁止JVM编译时指令重排序
公开课Singleton5 {//延迟加载//不稳定的关键字禁止指令重排序//解决双重校验也存在一个问题,jvm重排序的问题下会存在空指针问题 私有静态稳定Singleton5 singleton1=零; 公共静态Singleton5 getSingleton1 () { 如果(singleton1==null) { 同步(Singleton5.class) { 如果(singleton1==null) { singleton1=new Singleton5 (); } } } 返回singleton1; } } >之前
公开课Singleton6 {//延迟加载//静态内部类静态的始终在jvm中存在一份 静态类单例{ 私有静态Singleton6 singleton1=new Singleton6 (); } 公共静态Singleton6 get () { 返回Singleton.singleton1; } } >之前
公开课Singleton7 {//枚举类型是线程安全构造方法只会被装载一次 私人enum集合{ 单; 私人最终Singleton7 Singleton7; 单例(){ singleton7=new singleton7 (); } 公共Singleton7 getSingleton7 () { 返回singleton7; } }//延迟加载 公共静态Singleton7 get () { 返回Singleton.Singleton.getSingleton7 (); }//测试 公共静态void main (String [] args) { IntStream。rangeClosed (100)。forEach(我→{ 新线程(String.valueOf(我)){ @Override 公共空间run () { System.out.println (Singleton7.get ()); } } .start (); }); } }详解JAVA七种创建单例的方法