2024年java基础单例和框架单例

java基础单例和框架单例1 单例模式 单例模式 Singleton Pattern 是 Java 中最简单的设计模式之一 这种类型的设计模式属于创建型模式 它提供了一种创建对象的**方式 旨在确保一个类只有一个实例 并提供全局访问点来获取这个实例 单例模式在某些情况下非常有用 比如需要共享资源或管理全局状态的场景 1 1 单例模式的要点 唯一实例 类只能有一个实例 全局访问点 提供一个全局的访问点

大家好,我是讯享网,很高兴认识大家。



1. 单例模式

单例模式(Singleton Pattern) 是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的**方式,旨在确保一个类只有一个实例,并提供全局访问点来获取这个实例。单例模式在某些情况下非常有用,比如需要共享资源或管理全局状态的场景。

1.1 单例模式的要点

  1. 唯一实例:类只能有一个实例。
  2. 全局访问点:提供一个全局的访问点,用于获取该唯一实例。
  3. 防止外部创建实例:通过将构造方法设为私有,避免其他类直接创建对象。

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

1.2 单例模式的实现

单例设计模式分类两种:饿汉式、懒汉式。

饿汉式:类加载就会导致该单实例对象被创建。

饿汉式有三种实现方式:静态常量方式、静态代码块方式、枚举形式

懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建。

懒汉式有四种实现方式:线程不安全方式、线程安全方式、双重检查锁方式(线程安全方式优化)、静态内部类方式(线程安全方式优化)

1.3 饿汉式单例模式

1.3.1 静态常量方式

静态初始化,类加载时创建实例

  • 优点:这种写法比较简单,就是 在类加载的时候就完成实例化。避免了线程同步问题
  • 缺点:在类加载时就完成实例化,没有达到懒加载的效果。如果从未使用过这个实例,则会 造成内存的浪费

类图:

java基础单例和框架单例
image.png
 
讯享网 

1.3.2 静态代码块方式

将类实例化的过程放在了静态代码块中,也是在类加载的时候,就执行静态代码块中的代码,初始化类的实例。

  • 优缺点和上面的方式是一样的。

类图:

image.png
讯享网

1.3.3 枚举形式

通过枚举实现单例,是最推荐的实现方式,因为它简洁、线程安全,并且可以防止序列化和反射攻击。这种方式是Effective Java作者Josh Bloch 提倡的方式。

  • 优点:线程安全,防止反序列化破坏单例,简洁优雅。
  • 缺点:不适合需要延迟加载的情况。

类图:

image.png
 

1.4 懒汉式单例模式

1.4.1 线程不安全方式

该方式起到了懒加载的效果,但是只能在单线程下使用。如果在多线程下,一个线程进入了 判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以 在多线程环境下不可使用这种方式。在实际开发中,不要使用这种方式.

  • 优点:延迟加载实例,节省资源。
  • 缺点:在多线程环境下可能会创建多个实例,线程不安全。

类图:

image.png
讯享网

1.4.2 线程安全方式

该方式也起到了懒加载效果,同时又解决了线程安全问题。但是在 方法上添加了 关键字,导致该方法的执行效率特别低。从上面代码我们可以看出,其实就是在初始化 的时候才会出现线程安全问题,一旦初始化完成就不存在了。

  • 优点:延迟加载实例,节省资源。
  • 缺点:执行效率特别低。

类图:


image.png
 

1.4.3 双重检查锁方式(线程安全方式优化)

对于 方法来说,绝大部分的操作都是读操作,读操作是线程安全的。所以我们没必让每个线程必须持有锁才能调用该方法,我们需要调整加锁的时机,通过双重检查锁方式保证线程安全,同时确保懒加载。

类图:


image.png
 

1.4.4 静态内部类方式(线程安全方式优化)

静态内部类单例模式中实例由内部类创建,由于 JVM 在加载外部类的过程中, 是不会加载静态内部类的, 只有内部类的属性/方法被调用时才会被加载, 并初始化其静态属性。静态属性由于被 修饰,保证只被实例化一次,并且严格保证实例化顺序。

  • 优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高。
  • 缺点:无明显缺点,被认为是单例模式的**实践之一。

类图:


image.png
 

1.5 单例模式破坏方式

尽管单例模式的目的是确保一个类只有一个实例,但在某些特殊情况下,可以通过一些方法破坏单例模式的约束。以下是几种常见的破坏单例模式的方式以及对应的解决方案(以静态内部类方式为例)。

1.5.1 反射机制

的反射机制允许访问私有构造函数,即使构造函数是私有的,也可以通过反射调用,从而创建新的实例。

1.5.1.1 破坏方式

使用反射可以绕过单例类的私有构造方法,强行创建新的实例。

 
1.5.1.2 解决方案

可以在构造函数中加上检查,防止通过反射创建多个实例。

 

这种方式可以在实例化过程中,检测是否已有实例,如果存在,则抛出异常,防止反射破坏单例。

1.5.2 序列化

在使用 接口的情况下,反序列化会创建新的对象,破坏单例模式。

1.5.2.1 破坏方式

即使通过 方法获得了唯一实例,但序列化再反序列化会导致产生一个新的实例。

 
1.5.2.2 解决方案

可以通过实现 方法,在反序列化时确保返回已有实例。

 

方法在反序列化时会替换生成的实例,保证返回的是已有的单例对象。

1.5.3 克隆

如果类实现了 接口,并重写了 方法,克隆操作会生成一个新的实例,破坏单例模式。

1.5.3.1 破坏方式

通过克隆创建新实例。

 
1.5.3.2 解决方案

通过重写 方法,禁止克隆操作。

 

这种方式阻止了单例对象被克隆,从而保证唯一性。

1.6 JDK源码解析-Runtime类

从下面源代码中可以看出 类使用的是懒汉式单例模式(静态常量方式)来实现单例模式的。

小讯
上一篇 2024-12-28 23:11
下一篇 2024-12-25 17:38

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/8579.html