好记忆不如烂笔头,能记下点东西,就记下点,有时间拿出来看看,也会发觉不一样的感受.
单例设计模式是java中非常经典的设计模式,如下将好好讲解下java设计模式相关的知识。
1. 单例设计模式的前世今生
起源与背景
单例模式(Singleton Pattern)是设计模式中最为简单的一种模式,属于创建型模式。它的核心思想是确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。
在软件开发中,有些对象只需要一个实例,例如系统配置管理器、日志记录器、线程池等。如果这些对象被多次实例化,可能会导致资源浪费或逻辑冲突。因此,单例模式应运而生,用于解决这类问题。
发展历程
-
早期实现:在 Java 的早期版本中,单例模式的实现主要依赖于私有化构造函数和静态方法。通过将构造函数设置为私有,防止外部直接实例化对象,再通过静态方法提供一个全局访问点。
-
线程安全问题:随着多线程编程的发展,单例模式的线程安全性问题逐渐暴露。如果多个线程同时调用单例的获取方法,可能会导致多个实例被创建。因此,引入了同步机制(如
synchronized)来解决这一问题。 -
性能优化:使用同步方法虽然解决了线程安全问题,但可能会带来性能瓶颈。因此,出现了双重检查锁定(Double-Check Locking)和初始化按需持有类(Initialization-on-demand Holder)等优化方式。
-
现代实现:在 Java 5 之后,引入了
enum枚举来实现单例模式,这种方式不仅简单,而且天然线程安全,成为一种推荐的实现方式。
2. 单例设计模式的使用场景
单例模式适用于以下场景:
资源共享
-
配置管理器:系统中通常只需要一个配置管理器实例来加载和管理配置信息,避免重复加载配置文件。
-
日志记录器:日志记录器通常只需要一个实例,用于统一管理日志的输出,避免多个实例对日志文件的并发写入。
系统全局状态
-
线程池:线程池通常只需要一个实例,用于管理线程资源,避免过多线程的创建和销毁。
-
缓存管理器:缓存管理器通常只需要一个实例,用于管理缓存数据,避免多个实例之间的数据不一致。
性能优化
-
数据库连接池:数据库连接池通常只需要一个实例,用于管理数据库连接资源,避免频繁创建和销毁连接。
-
文件系统管理器:文件系统管理器通常只需要一个实例,用于管理文件资源,避免多个实例对文件系统的并发操作。

3. 单例设计模式的使用注意事项
线程安全
-
同步机制:如果单例模式的实现中涉及到多线程环境,必须确保线程安全。可以使用
synchronized同步方法或同步代码块来防止多个线程同时创建实例。 -
双重检查锁定:在使用双重检查锁定时,必须将实例变量声明为
volatile,以防止指令重排序问题。
序列化问题
-
反序列化:如果单例类实现了
Serializable接口,反序列化时可能会创建新的实例。可以通过实现readResolve()方法来解决这一问题,确保反序列化时返回同一个实例。
序列化问题
-
反射破坏:如果单例类的构造函数被反射调用,可能会破坏单例模式。可以通过在构造函数中添加额外的检查逻辑来防止反射破坏。
性能优化
-
懒汉式加载:如果单例实例的创建开销较大,可以使用懒汉式加载(延迟初始化),但需要确保线程安全。
-
饿汉式加载:如果单例实例的创建开销较小,可以使用饿汉式加载(在类加载时初始化),避免线程安全问题。
4. 单例模式的代码样例
以下是几种常见的单例模式实现方式及其代码样例:
饿汉式(线程安全,但可能浪费资源)
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
// 私有构造函数,防止外部实例化
if (instance != null) {
throw new IllegalStateException("Already initialized");
}
}
public static Singleton getInstance() {
return instance;
}
}
懒汉式(线程安全,但性能较差)
public class Singleton {
private static Singleton instance;
private Singleton() {
// 私有构造函数,防止外部实例化
if (instance != null) {
throw new IllegalStateException("Already initialized");
}
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
双重检查锁定(线程安全且性能较好)
public class Singleton {
private static volatile Singleton instance;
private Singleton() {
// 私有构造函数,防止外部实例化
if (instance != null) {
throw new IllegalStateException("Already initialized");
}
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
初始化按需持有类(线程安全且性能较好)
public class Singleton {
private Singleton() {
// 私有构造函数,防止外部实例化
if (Holder.INSTANCE != null) {
throw new IllegalStateException("Already initialized");
}
}
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
枚举实现(线程安全且简单)
public enum Singleton {
INSTANCE;
// 可以添加其他方法
public void someMethod() {
System.out.println("Singleton method called");
}
}
总结
单例模式是一种简单而强大的设计模式,适用于需要全局唯一实例的场景。在使用单例模式时,需要注意线程安全、序列化和反射破坏等问题,并根据实际需求选择合适的实现方式。

1188

被折叠的 条评论
为什么被折叠?



