当前位置: 首页 > news >正文

做网站订金为什么需要交那么多宁德市公共资源交易中心

做网站订金为什么需要交那么多,宁德市公共资源交易中心,做网站需要多少钱,深圳网站建设好上一篇博客已经介绍了设计模式及其设计原则, 在这篇博客中笔者会介绍一下单例模式, 也是最简单的一种设计模式 单例模式 单例模式属于创建型模式. 它涉及到一个单一的类, 该类负责创建自己的对象, 同时确保只有单个对象被创建, 这个类提供了一种访问其唯一对象的方式, 可以直…

上一篇博客已经介绍了设计模式及其设计原则, 在这篇博客中笔者会介绍一下单例模式, 也是最简单的一种设计模式

单例模式

单例模式属于创建型模式. 它涉及到一个单一的类, 该类负责创建自己的对象, 同时确保只有单个对象被创建, 这个类提供了一种访问其唯一对象的方式, 可以直接访问, 不需要实例化这个类的对象

单例模式结构

  • 单例类. 只能创建一个实例的类
  • 访问类. 使用单例类

单例模式实现

  1. 饿汉式单例

特点: 在类加载时就创建实例, 线程安全, 但是可能会导致资源浪费

public class Singleton {// 在类加载时就创建实例instanceprivate static final Singleton instance = new Singleton();// 私有的构造函数, 避免从外部构造新实例private Singleton() {}// 提供一个全局访问的接口, 可以获取已经创建好的单个实例instancepublic static Singleton getInstance() {return instance;}
}
  1. 懒汉式单例

特点: 延迟创建实例, 但是线程不安全

public class Singleton {// 单个的实例private static Singleton instance;// 私有的构造函数, 避免从外部构造新实例private Singleton() {}// 提供一个全局访问的接口, 可以获取已经创建好的单个实例instancepublic static Singleton getInstance() {// 假如这时instance还没有被创建, 那么就创建一个新的实例instanceif (instace == null) {instance = new Singleton();}return instance;}
}

懒汉式单例模式在多线程环境下容易导致线程不安全, 这是因为多个线程可能会同时访问 getInstance() 方法并且同时进入 if (instance == null) 代码块, 这样就会创建多个实例, 违背了单例模式的原则.

  1. 线程安全的懒汉式单例

特点: 延迟创建实例, 使用同步方法保证线程安全, 但是会有性能开销

public class Singleton {// 单个的实例private static Singleton instance;// 私有的构造函数, 避免从外部构造新实例private Singleton() {}// 提供一个全局访问的接口, 可以获取已经创建好的单个实例instance, 使用同步方法保证线程安全public static synchronized Singleton getInstance() {// 假如这时instance还没有被创建, 那么就创建一个新的实例instanceif (instace == null) {instance = new Singleton();}return instance;}
}
  1. 双重检查锁

特点: 提高性能, 减少同步开销, 线程安全

public class Singleton {// 单个的实例private static Singleton instance;// 私有的构造函数, 避免从外部构造新实例private Singleton() {}// 提供一个全局访问的接口, 可以获取已经创建好的单个实例instancepublic static Singleton getInstance() {// 第一次判断实例是否为null, 如果不为null就直接返回实例, 不进入抢锁阶段if (instance == null) {synchronized (Singleton.class) {// 抢到锁了再判断一次是否为nullif (instance == null) {instance = new Singleton();}}}return instance;}
}

双重检查锁模式可能会出现空指针问题, 出现问题的原因是JVM在实例对象时会进行优化和指令重排序操作

为了解决空指针异常问题, 可以使用 volatile 关键字, volatile 关键字可以保证可见性和有序性

public class Singleton {// 单个的实例, 使用volatile关键字保证其可见性和有序性private static volatile Singleton instance;// 私有的构造函数, 避免从外部构造新实例private Singleton() {}// 提供一个全局访问的接口, 可以获取已经创建好的单个实例instancepublic static Singleton getInstance() {// 第一次判断实例是否为null, 如果不为null就直接返回实例, 不进入抢锁阶段if (instance == null) {synchronized (Singleton.class) {// 抢到锁了再判断一次是否为nullif (instance == null) {instance = new Singleton();}}}return instance;}
}

笔者写到这一段的时候突然想到, 如果把上面双重检查锁的代码略改一下, 改成下面这样, 是否可行?

// Double-Checked Locking version 1
public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {instance = new Singleton();}}return instance;
}
//======================================
// Double-Checked Locking version 2
public static Singleton getInstance() {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}return instance;
}

上面的两种改法, 分别是把synchronized同步块内和同步块外的判断语句 if (instance == null) 删掉之后得到的新代码.

上面这两种改法是否可行呢? 其实都不好. 对于版本1, 假设有线程1和线程2, 进行了如下操作

---------------------------------------------------------Thread 1                    Thread 2|                            ||                            ||                            ||                            |
走到synchronized代码块处                 |
拿到锁之后发生了一次线程切换               ||                            ||                        走到synchronized代码块处, 拿不到锁, 被阻塞|                        线程切换|                            |
Thread 1创建了一个新实例                 |
Thread 1离开了synchronized代码块         |
锁被释放                                 |
线程切换                                 ||                            ||                            ||                        Thread 2拿到锁|                        Thread 2创建了新实例 (这里违背了单例模式原则)|                        Thread 2离开了synchronized代码块|                        Thread 2返回了创建的实例|                        线程切换|                            |
Thread 1返回创建的实例                   |
---------------------------------------------------------

这就和线程不安全的懒汉单例模式一样了

对于版本2, 其实和使用同步代码块的懒汉单例模式也是一样的, 线程是安全的, 但是性能开销依然存在

  1. 静态内部类

特点: 利用类加载机制实现懒加载, 线程安全

public class Singleton {// 私有的构造函数, 避免从外部构造新实例private Singleton() {}// 静态内部类, 延迟加载private static class SingletonHelper {private static final Singleton INSTANCE = new Singleton();}// 提供一个全局访问的接口, 可以获取已经创建好的单个实例instancepublic static Singleton getInstance() {return SingletonHelper.INSTANCE;}
}
  1. 枚举单例

特点: 简单, 线程安全, 防止反序列化导致创建新的实例

public enum Singleton {INSTANCE;// 其他方法public void someMethod() {// do something}
}

单例模式被破坏的情况

除了枚举单例模式之外, 其他单例模式都可以被破坏. 破坏单例模式的方法有两种, 分别为 序列化反射

  1. 序列化破坏单例模式

因为在序列化和反序列化过程中, 会创建一个新的实例, 即使单例类在内存中有一个唯一的实例, 通过反序列化也能创建多个实例, 这样就破坏了单例模式的初衷

假设有一个单例类如下:

import java.io.Serializablepublic class Singleton implements Serializable {private static final long serialVersionUID = 1L;private static final Singleton instance = new instance();private Singleton();public Singleton getInstance() {return instance;}// other methods...
}

破坏单例模式的场景

import java.io.*;public class SingletonDemo {public static void main(String[] args) {try {Singleton instance1 = Singleton.getInstance();// 序列化ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("singleton.ser"));out.writeObject(instance1);out.close();// 反序列化ObjectInputStream in = new ObjectInputStream(new FileInputStream("singleton.ser"));Singleton instance2 = (Singleton) in.readObject();in.close;System.out.println("Instance 1 hash code: " + instance1.hashCode());System.out.println("Instance 2 hash code: " + instance2.hashCode());} catch (Exception e) {e.printStackTrace();}}
}

运行 SingletonDemo, 发现 instance1instance2 的哈希码并不相同, 说明它们是不同的实例, 这就破坏了单例模式

为了防止序列化破坏单例模式, 可以在单例类中定义 readResolve 方法, 这个方法在反序列化时会被调用, 返回当前的单例实例, 从而确保反序列化得到的始终是唯一的单例实例

改进之后的单例类

import java.io.Serializablepublic class Singleton implements Serializable {private static final long serialVersionUID = 1L;private static final Singleton instance = new instance();private Singleton();public Singleton getInstance() {return instance;}// 添加readResolve方法protected Object readResolve() {return getInstance();}// other methods...
}

再次运行 SingletonDemo , 发现 instance1instance2 的哈希码是相同的, 因此它们是同一个实例, 单例模式没有被破坏.

  1. 反射破坏单例模式

因为反射允许我们访问私有构造方法, 从而构建多个对象, 这就违背了单例模式的初衷

假设有一个单例类如下:

public class Singleton {private static final Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}
}

破坏单例模式的场景

import java.lang.reflect.Constructor;public class SingletonDemo {public static void main(String[] args) {try {Singleton instance1 = Singleton.getInstance();// 通过反射创建新的实例Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();constructor.setAccessible(true);Singleton instance2 = constructor.newInstance();// 检查两个实例是否相同System.out.println("Instance 1 hash code: " + instance1.hashCode());System.out.println("Instance 2 hash code: " + instance2.hashCode());} catch (Exception e) {e.printStackTrace();}}
}

运行 SingletonDemo, 发现 instance1instance2 的哈希码并不相同. 说明它们是不同的实例, 单例模式被破坏

为了防止反射破坏单例模式, 可以在构造方法中添加防御措施, 例如在构造方法中检测实例是否存在, 如果存在就抛出异常

改进之后的单例类

public class Singleton {private static final Singleton instance = new Singleton();private Singleton() {// 防止反射创建新的实例if (instance != null) {throw new RuntimeException("Use getInstance() method to get the single instance of this class.");}}public static Singleton getInstance() {return instance;}
}

再次运行 SingletonDemo, 发现反射创建实例的步骤会抛出异常, 阻止了反射破坏单例模式


最近在学设计模式, 可能会高强度更新设计模式相关的技术博客. 对设计模式感兴趣的读者可以关注我的 CSDN Channel, 掘金 Channel, 我的个人博客网站 或 网站的镜像站点

http://www.khdw.cn/news/46819.html

相关文章:

  • 免费营销型网站b站推广网站2023
  • 哪个汽车网站汽贸店免费做数据分析师就业前景
  • 免费网站模板无需注册甘肃网站推广
  • 北京房山网站建设产品更新培训广州做seo的公司
  • 做vlog网站推荐互联网推广销售
  • 苏州工业园区建设局网站百度移动点击排名软件
  • 网页界面布局怎么优化一个网站关键词
  • 旗袍网站架构优化设计六年级上册数学答案
  • wordpress恢复阿里云今日头条seo
  • 郑州上市企业网站建设关键词优化方法
  • 浙江省住房城乡建设厅网站首页国际军事最新消息今天
  • 做电影网站要多少钱先做后付费的代运营
  • 北京外包做网站如何报价整站优化seo
  • 拱墅网站建设seo交流论坛seo顾问
  • wordpress数据库meta技术教程优化搜索引擎整站
  • 方城网站制作qq群推广平台
  • 怎么做自己的单页网站seo体系
  • 黄石做网站联系推广下载
  • 免费建筑图纸下载网站网站域名解析
  • 网站访问流量怎么赚钱seo推广教程seo高级教程
  • 赤峰北京网站建设百度关键词搜索排名多少钱
  • 做网站推广要注意什么海东地区谷歌seo网络优化
  • 如何做网站怎么赚钱seo待遇
  • wordpress iphone appaso优化是什么
  • 郑州网站制作生产厂商定制登封搜索引擎优化
  • 做jsp网站用哪些软件下载上海百度公司地址在哪里
  • 成都做网站设计哪家便宜自媒体平台注册入口
  • 太仓市娄城高新建设有限公司网站网站制作推广电话
  • 网络品牌推广计划网络快速排名优化方法
  • 安装wordpress素锦网站怎么seo关键词排名优化推广