深圳住房和建设厅网站首页,图片生成链接的网站,wordpress小工具找不到,网络安全工程师年薪目录
1.设计模式是啥#xff1f;
2.单例模式
2.1什么是单例模式
2.2饿汉模式
2.3懒汉模式
3.懒汉模式与饿汉模式的区别
3.1.线程安全方面
3.2.资源加载和性能
4.如何保证懒汉模式的线程安全 1.设计模式是啥#xff1f;
设计模式是前人经过总结#xff0c;通过…目录
1.设计模式是啥
2.单例模式
2.1什么是单例模式
2.2饿汉模式
2.3懒汉模式
3.懒汉模式与饿汉模式的区别
3.1.线程安全方面
3.2.资源加载和性能
4.如何保证懒汉模式的线程安全 1.设计模式是啥
设计模式是前人经过总结通过对不同应用场景应该运用何种方法解决问题的模式。我们可以将它看成NBA中的战术例如电梯门战术在应对不同的队伍时需要运用不同的战术针对不一样的队伍用不一样的战术才能更高效的得分这就相当于对不同的问题有固定的模板免得去思考可以直接去使用。故可认为它是解决待定问题的一系列套路是前辈们的代码设计经验的总结具有一定的普遍性可以重复使用。其目的是为了提高代码的可重用性、代码的可读性和代码的可靠性。
2.单例模式
2.1什么是单例模式
这个就看字面意思就很好理解就是只能有一个例子也就是该类只能new一个对象。
官方的说就是这种模式涉及到一个单一的类该类负责创建自己的对象同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式可以直接访问不需要实例化该类的对象。 目前单例模式有两种1.饿汉式 2.懒汉式 如何实现单例模式呢我们就从者两个模式的具体实现来说明吧
2.2饿汉模式 饿汉式单例模式实现步骤
1.将构造器私有化 解释防止用户构造新对象
2.在类中创建好一个对象 解释因为我们把构造器进行了私有化操作但我们单例模式中需要有个对象因此我们需要在类中实例化好一个对象。
3.创建一个方法或者类中创建好的对象 解释因为我们外部不能创建对象但是我们类中有创建好的对象因此我们需要一个方法来将对象给取出来。
代码实现
class Singleton {private static Singleton instancenew Singleton();public static Singleton getS() {return instance;}private Singleton(){};
}
public class testDemo1 {public static void main(String[] args) {Singleton singletonSingleton.getS();}
}注意
观察代码有几个细节需要注意因为用户不可以创建对象因此我们需要在类中创建好对象不能创建对象就意味着我们不能通过对象引用类中的成员方法与成员变量即在类中new对象时和获得new好的对象时需要用静态成员变量和静态成员方法通过类名来访问。
2.3懒汉模式 懒汉式单例模式实现步骤
1.将构造器私有化 解释防止用户构造新对象
2.在类中创建好一个对象 解释因为我们把构造器进行了私有化操作但我们单例模式中需要有个对象因此我们需要在类中实例化好一个对象。
3.创建一个方法或者类中创建好的对象 解释因为我们外部不能创建对象但是我们类中有创建好的对象因此我们需要一个方法来将对象给取出来。
class SingleLazy{private static SingleLazy instancenull;public static SingleLazy getInstance() {if(instancenull) {instancenew SingleLazy();}return instance;}private SingleLazy() {}
}
public class testDemo2 {SingleLazy singleLazySingleLazy.getInstance();
}注意
观察代码有几个细节需要注意因为用户不可以创建对象因此我们需要在类中创建好对象不能创建对象就意味着我们不能通过对象引用类中的成员方法与成员变量即在类中new对象时和获得new好的对象时需要用静态成员变量和静态成员方法通过类名来访问。
与饿汉模式不同之处时懒汉模式只有在调用到这个对象时对象才得以创建在没有调用之前创建出来的对象时null懒汉模式要比饿汉模式节省一些不必要的资源。
3.懒汉模式与饿汉模式的区别
3.1.线程安全方面
饿汉式天生就是线程安全的因为饿汉模式当中仅仅只有读操作可以直接用于多线程而不会出现问题懒汉式本身是非线程安全的懒汉模式线程不安全是因为他在创造对象时会产生指令重排序。
3.2.资源加载和性能
饿汉式在类创建的同时就实例化一个静态对象出来不管之后会不会使用这个单例都会占据一定的内存但是相应的在第一次调用时速度也会更快因为其资源已经初始化完成。
懒汉式顾名思义会延迟加载在第一次使用该单例的时候才会实例化对象出来第一次调用时要做初始化如果要做的工作比较多性能上会有些延迟。
4.如何保证懒汉模式的线程安全 首先我们要了解什么是线程不安全 抢占式执行 修改操作不是原子性的 内存可见性引发的线程不安全 指令重排序引发的线程不安全 多线程修改同一个变量引发的线程不完全 具体的上方具体解读可以参考这篇文章理解【JavaEE】 多线程的风险-线程安全 我们对标一下在懒汉模式中有几条是符合上方条件的 在懒汉模式getInstance()方法中对instance对象即包括了读操作也包括了写操作在操作时会发生指令重排序这对于多线程是不完全的。
这样说不是很只管我们画图来说明这里的例子仅代表一种情况 这种情况我们如何避免呢很好整不同的问题我们就不同的方案来解决这时的解决方法就是给代码加锁。 这样我们就可以阻止指令重排序让写操作在同一个线程内完成了
真的就完成了吗
并非如此试想在instance初始化之前还是instance初始化之后都会导致阻塞存在大量的锁竞争因此导致程序运行速度减慢哪有一本万利的生意。
因此对于防止过多的锁竞争我们需要再次改进代码再加入一个判断虽然有两个相同的if判断但是两个判断的初心不同,判断instance是否初始化如果已经初始化过了就不需要再次加锁了。 还有一个问题没有解决就是内存可见性的问题。
如果有多个线程都调用getInstance()方法就会有大量的读instance操作我们知道对于访问内存与寄存器访问寄存器的速度要比内存高几个数量级因此编译器就会自作主张优化掉访问内存的操作即将读内存的操作优化为读寄存器的操作。
为了保证内存可见性我们需要将 在创建instance对象的语句上加上volatile关键字来保证内存可见性。
完整代码如下
class SingleLazy{private volatile static SingleLazy instancenull;//创建一个实例对象public static SingleLazy getInstance() {//判断是否需要加锁if(instancenull) {synchronized (SingleLazy.class) {//判断对象是否实例化if (instance null) {instance new SingleLazy();}}}return instance;}private SingleLazy() {}
}写在最后
以上就是本文全部内容如果对你有所帮助希望能留下你的点赞关注我会更加努力的更新内容非常感谢
若本篇文章有错误的地方欢迎大佬们指正