高端网站设计哪家好,机械加工网登录,凡客诚品是干嘛的,seo引擎优化专员阿华代码#xff0c;不是逆风#xff0c;就是我疯#xff0c;你们的点赞收藏是我前进最大的动力#xff01;#xff01;希望本文内容能够帮助到你#xff01;
目录 一#xff1a;单例模式#xff08;singleton#xff09;
1#xff1a;概念
二#xff1a;“饿汉模…阿华代码不是逆风就是我疯你们的点赞收藏是我前进最大的动力希望本文内容能够帮助到你
目录 一单例模式singleton
1概念
二“饿汉模式”
1前引
2代码编译
3代码分析
4解释为什么叫“饿汉模式”
三“懒汉”模式
1前引
2代码编译
3代码分析
4“懒汉”的优点
5比较“饿汉”和“懒汉”
四“饿汉”模式线程安全问题
五“懒汉”模式的线程安全问题
1重复创建实例
2解决问题
1解决思路的核心本质
2缺点
①效率降低
②不可预期
3优化效率问题
1问题解释
2解决方法
六指令重排序问题
前引
1代码拆分三指令
2分析
3代码解释
4解锁思路
1复习volatile两个功能 一单例模式singleton
1概念
单例模式就是在java进程中要求指定的类只能有一个对象
我们通过一些特殊的技巧来确保我们的实例对象只有一个——换句话说就是如果我们尝试new多个实例编译器就会报错。
二“饿汉模式”
1前引
1知识科普
我们先认识俩个单词——singleton单例模式和getInstance获取实例
2每个类只能有一个类对象比如Thread类Thread.class获取到Thread这个类的类对象它是从.class文件加载到内存当中的
2代码编译
package thread;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-24* Time: 13:20*/
class Singleton{private static Singleton instance new Singleton();public static Singleton getInstance(){//返回值类型为Singletonreturn instance;}private Singleton(){//静态构造方法让你访问不到}}
public class ThreadDemon28 {//“饿汉模式”public static void main(String[] args) {Singleton s1 Singleton.getInstance();Singleton s2 Singleton.getInstance();System.out.println(s1 s2);//判断s1和s2是否指向的是同一个对象}
}3代码分析 最后我们在main方法中比较s1s2获取到的地址是否相同s1s2所指向的对象
4解释为什么叫“饿汉模式”
因为我们在类加载的时候就创建了这个实例初始化静态成员变量这个时机非常的早——相当于程序一启动实例就创建好了。所以就用“饿汉”来形容创建实例非常的迫切非常早
三“懒汉”模式
1前引
“懒汉”模式相对于“饿汉”模式不同的地方在于创建实例的时机更加晚一些下面我们通过代码来进行展示
2代码编译
package thread;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-24* Time: 13:52*/
class SingletonLazy{private static SingletonLazy instance null;public static SingletonLazy getInstance(){if (instance null){ //如果instance为null则进入if创建实例创建实例的时机是第一次调用getInstance这个方法instance new SingletonLazy();}return instance;//第二次第三次调用getInstance()这个方法就不会进入if语句中而直接返回instance了}private SingletonLazy(){}
}
public class ThreadDemon29 {public static void main(String[] args) {SingletonLazy s1 SingletonLazy.getInstance();SingletonLazy s2 SingletonLazy.getInstance();System.out.println(s1 s2);}}3代码分析
很明显的不同是初始instance初始化为null并没有实例化对象只有第一次调用了getInstance方法后才会实例化SingletonLazy
4“懒汉”的优点
例如现在有一个非常大的文件1个G
“饿汉”模式会直接把一个G全部加载到内存中在进行展示。
“懒汉”模式会先加载100kb的数据到内存中随着用户的翻页在逐步的加载到内存当中
5比较“饿汉”和“懒汉”
1创建时机上“饿汉”更早
2“饿汉”创建实例依赖于程序驱动“懒汉”创建实例依赖于调用方法 四“饿汉”模式线程安全问题 对于饿汉模式无论有多少个线程在调用getInstance 方法都会返回instance对于return这一条代码来说只有一个“读操作”线程是非常安全的 五“懒汉”模式的线程安全问题
1重复创建实例
①看下面这个例子我们拆分if里面的代码会发现实例被new了两次这就不是单例模式了就有bug了
②有人说不就是多new了个对象嘛问题不大~~~。但是对于单例模式来说一个对象可能要管理10GB的内存或者更大多new一个对象就多翻了一倍的内存啊 2解决问题
想办法给if条件和创建实例进行打包——用关键字synchronized。
1解决思路的核心本质
是让if语句打包成一个整体成为“原子性操作”
2缺点
①效率降低
以下加锁的思路有一个致命缺点我们保证多线程下我们创建出来的实例就只有一个是通过“加锁”和“解锁”来解决的但是这个过程很耗费资源
②不可预期
一旦线程发生了阻塞那么什么时候解除阻塞我们是不可控制和预期的 3优化效率问题
1问题解释 2解决方法 六指令重排序问题
前引
指令重排序是编译器优化的一种方式调整原有代码的执行顺序保证逻辑不变的前提下提高程序的效率 1代码拆分三指令
上面这段代码可以分为三个指令来执行
①申请一段内存空间 买房子
②在这段内存上调用构造方法初始化实例 给房子装修
③把内存地址赋值给instance 拿到房子的钥匙
package thread;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-24* Time: 13:52*/
class SingletonLazy{private static Object locker1 new Object();private static SingletonLazy instance null;public static SingletonLazy getInstance(){if (instance null){synchronized(locker1){if (instance null){ //如果instance为null则进入if创建实例创建实例的时机是第一次调用getInstance这个方法instance new SingletonLazy();}}}return instance;//第二次第三次调用getInstance()这个方法就不会进入if语句中而直接返回instance了}private SingletonLazy(){}
}
public class ThreadDemon29 {public static void main(String[] args) {SingletonLazy s1 SingletonLazy.getInstance();SingletonLazy s2 SingletonLazy.getInstance();System.out.println(s1 s2);}}2分析
我们延用上面的代码
上述三个指令的执行顺序可以为①②③也可以为①③②
问题出现在如果执行顺序为①③②上 3代码解释
线程t1经过代码优化后先执行③赋值地址此时instance只是接收了一个地址它所指向的是一个尚未被初始化的对象这个对象啥也不是可以理解成“全为0”
恰巧此时线程t2插入进入if条件判断判断instance null线程t2以为实例已经创建完毕直接return instance假设t2紧接着调用instance里面的方法或者属性就会出现大问题。
4解锁思路
加入关键字volatile
1复习volatile两个功能
①保证内存可见性即每次访问变量都要重新读取内存而不会优化到寄存器或者缓存当中
②禁止指令重排序 此时针对变量的读写操作就不会出现重排序的问题了