node.js做网站泉州网站公司
- 作者: 多梦笔记
- 时间: 2026年02月17日 07:37
当前位置: 首页 > news >正文
node.js做网站,泉州网站公司,深圳建设集团有限公司好吗,深圳网站建设哪里便宜创建型模式提供创建对象的机制#xff0c;能够提升已有代码的灵活性和复用性。 常用的有#xff1a;单例模式、工厂模式#xff08;工厂方法和抽象工厂#xff09;、建造者模式。 不常用的有#xff1a;原型模式。
单例模式
单例模式介绍
1 ) 定义
单例模式#xf…创建型模式提供创建对象的机制能够提升已有代码的灵活性和复用性。 常用的有单例模式、工厂模式工厂方法和抽象工厂、建造者模式。 不常用的有原型模式。
单例模式
单例模式介绍
1 ) 定义
单例模式Singleton Pattern是 Java 中最简单的设计模式之一此模式保证某个类在运行期间只有一个实例对外提供服务而这个类被称为单例类。 单例模式也比较好理解比如一个人一生当中只能有一个真实的身份证号一个国家只有一个政府类似的场景都是属于单例模式场景。 2 ) 使用单例模式要做的两件事
保证一个类只有一个实例为该实例提供一个全局访问节点。
3 ) 单例模式结构
饿汉式
在类加载期间初始化静态实例保证instance实例的创建是线程安全的实例在类加载时实例化有 JVM 保证线程安全
特点不支持延迟加载实例懒加载此种方式类加载比较慢但是获取实例对象比较快
问题该对象足够大的话而一直没有使用就会造成内存的浪费。
public class Singleton_01 {//1. 私有构造方法private Singleton_01(){}//2. 在本类中创建私有静态的全局对象private static Singleton_01 instance new Singleton_01();//3. 提供一个全局访问点,供外部获取单例对象public static Singleton_01 getInstance(){return instance;}}懒汉式(线程不安全)
此种方式的单例实现了懒加载只有调用 getInstance() 方法时才创建对象。但是如果是多线程情况则会出现线程安全问题。
public class Singleton_02 {//1. 私有构造方法private Singleton_02(){}//2. 在本类中创建私有静态的全局对象private static Singleton_02 instance;//3. 通过判断对象是否被初始化,来选择是否创建对象public static Singleton_02 getInstance(){if(instance null){instance new Singleton_02();}return instance;}
}假设在单例类被实例化之前有两个线程同时在获取单例对象线程A在执行完if (instance null) 后线程的调度机制将 CPU 资源分配给线程B此时线程B在执行 if (instance null)时也发现单例类还没有被实例化这样就会导致单例类被实例化两次。为了防止这种情况发生需要对getInstance()方法同步处理。下面是改进后的懒汉模式。
懒汉式(线程安全)
原理使用同步锁synchronized 锁住创建单例的方法防止多个线程同时调用从而避免造成单例被多次创建。
即 getInstance() 方法块只能运行在1个线程中若该段代码已在1个线程中运行另外1个线程试图运行该块代码则 会被阻塞而一直等待 在这个线程安全的方法里我们实现了单例的创建保证了多线程模式下单例对象的唯一性。
public class Singleton_03 {//1. 私有构造方法private Singleton_03(){}//2. 在本类中创建私有静态的全局对象private static Singleton_03 instance;//3. 通过添加synchronize,保证多线程模式下的单例对象的唯一性public static synchronized Singleton_03 getInstance(){if(instance null){instance new Singleton_03();}return instance;}}小结懒汉式的缺点也很明显我们给 getInstance() 这个方法加了一把大锁synchronzed导致这个函数的并发度很低。量化一下的话并发度是 1也就相当于串行操作了。而这个函数是在单例使用期间一直会被调用。如果这个单例类偶尔会被用到那这种实现方式还可以接受。但如果频繁地用到那频繁加锁、释放锁及并发度低等问题会导致性能瓶颈这种实现方式显然就不可取了。
双重校验
饿汉式不支持延迟加载懒汉式有性能问题不支持高并发。那么我们再来看一种既支持延迟加载、又支持高并发的单例实现方式也就是双重检测实现方式。
实现步骤
在声明变量时使用了 volatile 关键字,其作用有两个。 保持变量的可见性当一个被volatile 关键字修饰的变量被一个线程修改的时候其他线程可立刻得到修改之后的结果屏蔽指令重排序指令重排序是编译器和处理器为了高效对程序进行优化的手段它只能保证程序执行的结果时正确的但无法保证程序的操作顺序与代码顺序一致。这在单线程中不会构成问题但在多线程中就会出现问题。 将同步方法修改为同步代码块。在同步代码块中使用二次检查以保证其不被重复实例化同时在调用 getInstance() 方法时不进行同步锁效率高。
/*** 单例模式-双重校验**/
public class Singleton_04 {//使用 volatile保证变量的可见性private volatile static Singleton_04 instance null;private Singleton_04(){}//对外提供静态方法获取对象public static Singleton_04 getInstance(){//第一次判断,如果instance不为null,不进入抢锁阶段,直接返回实例if(instance null){synchronized (Singleton_04.class){//抢到锁之后再次进行判断是否为nullif(instance null){instance new Singleton_04();}}}return instance;}
}在双重检查锁模式中为什么需要使用volatile关键字 在 JAVA 内存模型中volatile关键字作用可以保证可见性或禁止指令重排。这里是因为 singleton new Singleton()它并非是一个原子操作事实上在JVM中上述语句至少做了以下3件事。
给 singleton 分配内存空间;开始调用 Singleton 的构造函数等来初始化 singleton;将 singleton 对象指向分配的内存空间执行玩这步 singleton 就不是 null。
这里需要留意一下 1-2-3 的顺序因为存在指令重排序的优化也就是说第 2 步和第 3 步的顺序是不能保证的最终的执行顺序可能是 1-2-3也有可能是 1-3-2。
如果是 1-3-2那么在第 3 步执行完以后singleton 就不是 null 了可是这时第 2 步并没有执行singleton 对象未完成初始化它的属性的值可能不是我们所预期的值。假设此时线程 2 进入 getInstance 方法由于 singleton 已经不是 null 了所以会通过第一重检查并直接返回但其实这时的 singleton 并没有完成初始化因此使用这个实例的时候会报错。
详细流程如下图所示。
线程 1 首先执行新建实例的第一步也就是分配单例对象的内存空间由于线程 1 被重排序所以执行了新建实例的第三步也就是把 singleton 指向之前分配出来的内存地址在这第三步执行之后singleton 对象便不再是 null。 这时线程 2 进入 getInstance 方法判断 singleton 对象不是 null紧接着线程 2 就返回 singleton 对象并使用由于没有初始化所以报错了。最后线程 1 “姗姗来迟”才开始执行新建实例的第二步——初始化对象可是这时的初始化已经晚了因为前面已经报错了。 使用了volatile之后相当于是表明了该字段的更新可能是在其他线程中发生的因此应确保在读取另一个线程写入的值时可以顺利执行接下来所需的操作。在 JDK 5 以及后续版本所使用的 JMM 中在使用了volatile后会一定程度禁止相关语句的重排序从而避免了上述由于重排序所导致的读取到不完整对象的问题的发生。
静态内部类
原理根据静态内部类的特性(外部类的加载不影响内部类)同时解决了按需加载、线程安全的问题同时代码实现也简洁。
在静态内部类里创建单例在装载该内部类时才会去创建单例线程安全类是由 JVM加载而JVM只会加载1遍保证只有1个单例
public class Singleton_05 {private static class SingletonHandler{private static Singleton_05 instance new Singleton_05();}private Singleton_05(){}public static Singleton_05 getInstance(){return SingletonHandler.instance;}
}反射对于单例的破坏
概念 JAVA反射机制是在运行状态中对于任意一个类都能够知道这个类的所有属性和方法对于任意一个对象都能够调用它的任意方法和属性这种动态获取信息以及动态调用对象方法的功能称为JAVA语言的反射机制。
反射技术过于强大它可以通过setAccessible()来修改构造器字段方法的可见性。单例模式的构造方法是私有的如果将其可见性设为public那么将无法控制对象的创建。
public class Test_Reflect {public static void main(String[] args) {try {//反射中欲获取一个类或者调用某个类的方法首先要获取到该类的Class 对象。ClassSingleton_05 clazz Singleton_05.class;//getDeclaredXxx: 不受权限控制的获取类的成员.Constructor c clazz.getDeclaredConstructor(null);//设置为true,就可以对类中的私有成员进行操作了c.setAccessible(true);Object instance1 c.newInstance();Object instance2 c.newInstance();System.out.println(instance1 instance2);} catch (Exception e) {e.printStackTrace();}}
}解决方法之一 在单例类的构造方法中 添加判断 instance ! null 时直接抛出异常。
public class Singleton_05 {private static class SingletonHandler{private static Singleton_05 instance new Singleton_05();}private Singleton_05(){if(SingletonHandler.instance ! null){throw new RuntimeException(不允许非法访问!);}}public static Singleton_05 getInstance(){return SingletonHandler.instance;}
}上面的这种方式使代码简洁性遭到了破坏设计得不够优雅。
相关文章
-
node js 网站开发黄石市城市建设档案馆网站
node js 网站开发黄石市城市建设档案馆网站
- 站长
- 2026年02月17日
-
nginx网站开发安徽安庆
nginx网站开发安徽安庆
- 站长
- 2026年02月17日
-
nginx 做网站网站开发图书系统前台模板
nginx 做网站网站开发图书系统前台模板
- 站长
- 2026年02月17日
-
nodejs可以做网站么一键logo生成器在线
nodejs可以做网站么一键logo生成器在线
- 站长
- 2026年02月17日
-
nodejs网站毕设代做凡客官网旗舰店
nodejs网站毕设代做凡客官网旗舰店
- 站长
- 2026年02月17日
-
notepad做网站技巧wordpress微信查看密码
notepad做网站技巧wordpress微信查看密码
- 站长
- 2026年02月17日
