网站备案有哪些费用网络科技公司企业文化
web/
2025/10/7 12:02:58/
文章来源:
网站备案有哪些费用,网络科技公司企业文化,动漫制作就业方向及前景,在ps中做网站首页的尺寸单例模式是校招中最常考的设计模式之一.
设计模式其实就是类似于“规章制度”#xff0c;按照这个套路来进行操作。
单例模式能保证某个类在程序中只存在唯一 一份实例。而不会创建出多个实例#xff0c;如果创建出了多个实例#xff0c;就会编译报错。而不会创建出多个实…单例模式是校招中最常考的设计模式之一.
设计模式其实就是类似于“规章制度”按照这个套路来进行操作。
单例模式能保证某个类在程序中只存在唯一 一份实例。而不会创建出多个实例如果创建出了多个实例就会编译报错。而不会创建出多个实例如果创建出了多个实例就会编译报错。不使用单例模式也可以做到就像跟别人借钱说我一定会还一样但是模式就相当于打了欠条一定得做到的。这一点在很多场景上都需要. 比如 JDBC 中的 DataSource 实例就只需要一个。
单例模式具体的实现方式, 分成 饿汉 和 懒汉 两种.
饿汉模式
类加载的同时, 创建实例给人一种很急的感觉
// 饿汉模式的 单例模式 实现.
// 此处保证 Singleton 这个类只能创建出一个实例.
class Singleton {// 在此处, 先把这个实例给创建出来了.private static Singleton instance new Singleton();// 如果需要使用这个唯一实例, 统一通过 Singleton.getInstance() 方式来获取.public static Singleton getInstance() {return instance;}// 为了避免 Singleton 类不小心被复制出多份来.// 把构造方法设为 private. 在类外面, 就无法通过 new 的方式来创建这个 Singleton 实例了!!private Singleton() {}
}public class ThreadDemo19 {public static void main(String[] args) {Singleton s Singleton.getInstance();Singleton s2 Singleton.getInstance();// Singleton s3 new Singleton();System.out.println(s s2);}
} 运行一个 Java 程序会先让 Java 进程找到并读取对应的 .class 文件就会读取文件内容并解析构造成类对象......这一系列的过程操作就叫做 类加载。 因为 static 修饰的变量落入到了类对象里面又因为类对象是在类加载阶段内创建出来的唯一一个实例同时构造方法是 private 修饰的因此就只有这一个实例的成员了。 懒汉模式
类加载的时候不创建实例第一次使用的时候才创建实例如果不用就不创建了效率更高了
class SingletonLazy {private static SingletonLazy instance null;public static SingletonLazy getInstance() {if (instance null) {instance new SingletonLazy();}return instance;}private SingletonLazy() {}
}public class ThreadDemo20 {public static void main(String[] args) {SingletonLazy s SingletonLazy.getInstance();SingletonLazy s2 SingletonLazy.getInstance();System.out.println(s s2);}
} 上述的这两种模式饿汉模式只涉及到“读操作”懒汉模式既涉及到“读操作”也涉及到“写操作”因此这个在多线程环境下会有线程安全问题。 因此加上 synchronized 可以改善这里的线程安全问题。
public static SingletonLazy getInstance() {// 这一层 if 是因为只要对象被 new 了一次就不用再加锁产生更多开销了if (instance null) {synchronized (SingletonLazy.class) {if (instance null) {instance new SingletonLazy();}}}return instance;} 也就是说如果对象还有没有创建那么就要进行加锁如果对象已经创建过了就不用加锁了因为最后都是“读操作”此时不加锁也没事。 懒汉模式-多线程版(改进) 假设有很多线程都去进行 getInstance这个时候就会出现内存可见性问题编译器优化只有第一次真正读了内存后续都是读寄存器 / cache 同时还会有指令重排序问题
instance new Singleton()可以拆分成三个步骤
1.申请内存空间
2.调用构造方法把这个内存空间初始化成一个合理的对象
3.把内存空间的地址赋值给 instance 引用 正常情况下是1 2 3 顺序来执行的但是编译器会为了提高效率从而调整顺序可能就变成1 3 2如果是单线程就没有区别。但在多线程环境下假设 t1 是按照 1 3 2 执行的当 t1 执行到 1 3 之后准备执行 2 的时候t2 跑过来执行了。此时在 t2 的角度 instance 就非空了就会直接返回instance 了但由于 t1 的 2 指令还没执行完t2 拿到的是一个非法的对象还没构造完成的不完整的对象这时候如果尝试使用引用中的属性就会出现错误。例如 instance 里有个成员 num构造方法是要初始化成100的但是由于上述问题就导致构造方法还没执行此时访问 num 是 0。 因此加上 volatile 可以解决内存可见性问题和禁止指令重排序。
class SingletonLazy {private volatile static SingletonLazy instance null;public static SingletonLazy getInstance() {if (instance null) {synchronized (SingletonLazy.class) { //加锁不是这个线程就一直赖着不走而是切换调度正常但是其他线程尝试加锁的时候就会阻塞。if (instance null) {instance new SingletonLazy();}}}return instance;}private SingletonLazy() {}
}public class ThreadDemo20 {public static void main(String[] args) {SingletonLazy s SingletonLazy.getInstance();SingletonLazy s2 SingletonLazy.getInstance();System.out.println(s s2);}
}
理解双重 if 判定 / volatile:
加锁 / 解锁是一件开销比较高的事情. 而懒汉模式的线程不安全只是发生在首次创建实例的时候.
因此后续使用的时候, 不必再进行加锁了.
外层的 if 就是判定下看当前是否已经把 instance 实例创建出来了.
同时为了避免 内存可见性 导致读取的 instance 出现偏差, 于是补充上 volatile .
当多线程首次调用 getInstance, 大家可能都发现 instance 为 null, 于是又继续往下执行来竞争锁,
其中竞争成功的线程, 再完成创建实例的操作.
当这个实例创建完了之后, 其他竞争到锁的线程就被里层 if 挡住了. 也就不会继续创建其他实例.
1) 有三个线程, 开始执行 getInstance , 通过外层的 if (instance null) 知道了实例还没
有创建的消息. 于是开始竞争同一把锁.
2) 其中线程1 率先获取到锁, 此时线程1 通过里层的 if (instance null) 进一步确认实例是
否已经创建. 如果没创建, 就把这个实例创建出来.
3) 当线程1 释放锁之后, 线程2 和 线程3 也拿到锁, 也通过里层的 if (instance null) 来
确认实例是否已经创建, 发现实例已经创建出来了, 就不再创建了.
4) 后续的线程, 不必加锁, 直接就通过外层 if (instance null) 就知道实例已经创建了, 从
而不再尝试获取锁了. 降低了开销.
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/88460.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!