网站运营策划方案,做视频网站利润如何处理,自贡网站设计,jquery win8风格企业网站模板在软件设计中#xff0c;有时我们希望某个类的实例始终是唯一的#xff0c;即无论在何处访问这个类#xff0c;都能够得到同一个实例。单例模式#xff08;Singleton Pattern#xff09;就是为了解决这个问题而产生的。单例模式确保一个类只有一个实例#xff0c;并提供一… 在软件设计中有时我们希望某个类的实例始终是唯一的即无论在何处访问这个类都能够得到同一个实例。单例模式Singleton Pattern就是为了解决这个问题而产生的。单例模式确保一个类只有一个实例并提供一个全局访问点。 1.定义 单例模式是一种创建型设计模式确保一个类只有一个实例并提供一个全局访问点来访问这个实例。其主要思想是将类的构造函数私有化并通过一个静态方法来控制实例的创建和访问。
2.常见实现方式 单例模式有多种实现方式下面介绍几种常见的实现方式
2.1饿汉式Eager Initialization
饿汉式是在类加载时就创建实例这样可以确保线程安全并且在类首次使用前完成实例化。
示例代码
public class Singleton {private static final Singleton INSTANCE new Singleton();private Singleton() {// 私有构造函数防止外部实例化}public static Singleton getInstance() {return INSTANCE;}
}优点简单易于理解线程安全 缺点类加载时即创建实例可能造成资源浪费
如果你一定会使用该类这种方式无疑是最简单的方法
2.2 懒汉式Lazy Initialization
懒汉式是在第一次调用 getInstance() 方法时创建实例。这种方式避免了饿汉式的资源浪费问题。
示例代码
public class Singleton {private static Singleton instance;private Singleton() {// 私有构造函数防止外部实例化}public static synchronized Singleton getInstance() {if (instance null) {instance new Singleton();}return instance;}
}优点实现简单延迟实例化避免资源浪费 缺点使用了 synchronized在高并发情况下性能可能较差
每次调用getInstance()都会进行同步检查这样会消耗不必要的资源不推荐使用
2.3双重检查锁Double-Checked Locking
双重检查锁在懒汉式的基础上通过减少使用 synchronized 来提高性能。
示例代码
public class Singleton {// volatile关键字确保多线程下的可见性和有序性(禁止字节码重排)private static volatile Singleton instance;private Singleton() {// 私有构造函数避免外部直接实例化}public static Singleton getInstance() {if (instance null) { // 第一次检查synchronized (Singleton.class) {if (instance null) { // 第二次检查instance new Singleton(); // 实例化}}}return instance; // 返回实例}
}
优点延迟实例化提高了性能 缺点实现复杂容易出错
同步代码块含义因为可能会有多个线程同时通过了第一次检查在进入同步块之后再次检查可以确保只有一个线程创建实例最大限度地在提升性能的条件下保证了线程安全。
emm… 个人不喜欢这种笨重写法
2.4 静态内部类Static Inner Class
这种方式使用了类加载机制来确保线程安全同时实现了延迟加载。
示例代码
public class Singleton {private Singleton() {// 私有构造函数防止外部实例化}// 静态内部类利用类加载机制保证线程安全且延迟加载private static class SingletonHolder {private static final Singleton INSTANCE new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}优点延迟实例化线程安全实现简单 缺点无法传递外部参数
这时候就会有同学要问了何为类加载机制问的好所谓类加载机制就算JVM 在加载类的过程中静态内部类 SingletonHolder 中的静态变量 INSTANCE 只会被实例化一次由JVM保证其线程安全性所以在多线程环境下可以安全地使用。
2.5 枚举Enum
这种方法是Effective Java作者Joshua Bloch推荐的单例实现方式之一它解决了传统单例模式实现中的一些问题比如序列化、反射攻击等。
示例代码
public enum Singleton {INSTANCE;public void doSomething() {// 业务方法}
}优点简洁线程安全防止反序列化破坏单例 缺点无法灵活控制实例化过程
使用方法
Singleton.INSTANCE.doSomething();特点和优势 线程安全性 枚举类型的实例创建是线程安全的JVM在加载枚举类型时会通过类加载器保证只实例化一次。因此多线程环境下也能保证单例的唯一性。 防止反射攻击 枚举类型的实例创建是由JVM控制的因此无法通过反射来创建枚举类的实例。这样可以防止反射攻击即使是在枚举类中添加了私有构造函数也不例外。 防止序列化问题 Java枚举类型在序列化和反序列化时会自动处理确保在序列化和反序列化过程中都是单例的。 简洁且高效 枚举实现单例模式非常简洁只需声明一个枚举类型即可不需要额外的代码来保证线程安全和单例特性。
3.单例模式的注意事项 线程安全确保在多线程环境下一个类只有一个实例。延迟加载尽量避免在类加载时就实例化除非明确知道实例一定会被使用。防止反射攻击通过在构造函数中添加判断来防止反射创建多个实例。防止反序列化破坏单例在实现 Serializable 接口时提供 readResolve 方法。
4.总结 五种创建单例的方式大家按需选择核心思想都是确保一个类只有一个实例并提供全局访问点没有最好的只有最适合的理解不同实现方式的优缺点可以帮助我们在实际开发中选择最合适的方案。