湖南做网站的公司有哪些,静态网站作品,wordpress汉化插件下载,菏泽网站设计培训单例模式 单例模式饿汉式懒汉式 单例模式
解释#xff1a;一个类只能有一个实例 单例模式可以分为两种 饿汉式 和 懒汉式
饿汉式
也被称为预加载#xff0c;即 在加载类的时候#xff0c;就将实例创建出来#xff0c;加载到内存#xff0c;不管之后会不会使用这个实例 … 单例模式 单例模式饿汉式懒汉式 单例模式
解释一个类只能有一个实例 单例模式可以分为两种 饿汉式 和 懒汉式
饿汉式
也被称为预加载即 在加载类的时候就将实例创建出来加载到内存不管之后会不会使用这个实例 主打一个饥不择食体现了贪心的思想。
public class HungrySingleton {//方式1静态变量private static HungrySingleton instance new HungrySingleton();//方式2静态代码块/*static {instance new HungrySingleton();}*///方式3枚举可以看 EnumSingleton.classpublic static HungrySingleton getInstance(){return instance;}
}
很明显我们还没有使用该对象就已经加载到了内存浪费内存 但是同时因为只有一此创建对象所以饿汉式是线程安全的
懒汉式
也成为懒加载即只有在使用该类时才创建需要的对象。 我很懒你不用我我就不创建对象
一般有四种实现方式
简单懒汉式不能用线程不安全Synchronized 同步方法一般不用线程安全但锁粒度太大效率较低双重检查锁可以用注意使用volatile 关键字保证单例对象的原子性静态内部类推荐使用
public class LazySingleton {private volatile static LazySingleton instance;/*** 简单懒汉式* 问题线程不安全一般不用* return*/public static LazySingleton getInstance01() {if(null instance){instance new LazySingleton();}return instance;}/*** synchronized* 解决了线程安全问题但效率低一般不用* return*/public synchronized static LazySingleton getInstance02() {if(null instance){instance new LazySingleton();}return instance;}/*** 双重检查锁模式* 降低锁的粒度只锁创建对象的代码块* 需要增加 volatile 来保证原子性防止jvm指令重排但同时屏蔽了JVM的一些代码优化* return*/public static LazySingleton getInstance03() {if(null instance){synchronized (LazySingleton.class){if(null instance){//防止重复创建对象instance new LazySingleton();}}}return instance;}/*** 静态内部类方式* 只有在使用时才会创建静态内部类推荐使用* return*/public static LazySingleton getInstance04() {return SingletonHolder.INSTANCE;}private static class SingletonHolder{private static final LazySingleton INSTANCE new LazySingleton();}
}这里解释下 为什么 双重检查锁要 使用 volatile 关键字 修饰单例对象 if判断以及其内存执行代码是非原子性的。其次new LazySingleton()无法保证执行的顺序性。 显然不满足原子性或者顺序性线程肯定是不安全的。 下面主要讲一下 new LazySingleton() 为什么不能保证顺序性。 设想一下创建一个对象应该分为几步 答案是三步如下 memoryallocate();//1:初始化内存空间 ctorInstance(memory);//2:初始化对象 instancememory();//3:设置instance指向刚分配的内存地址 jvm为了提高程序执行性能会对没有依赖关系的代码进行重排序也就是说上面2和3行代码可能被重新排序。 我用两个线程举例
时间片线程A线程Bt1初始化内存空间t2设置instance指向刚分配的内存地址t3判断instance 是否为空t4由于instanc不为空获取到一个空的实例化对象线程不安全t5初始化对象
volatile 关键字就是强制要求jvm 不进行指令重排按顺序执行当然也有一定的性能损失 volatile 其他相关知识 可以参考以下文章 https://blog.csdn.net/m0_50370837/article/details/124380385