单例模式是一种常用的设计模式,它确保一个类只有一个实例,并提供全局访问点。
实现单例模式有多种方式,最常用的是饿汉式和懒汉式两种。
饿汉式在类加载时就创建了实例,因此线程安全但可能会造成资源浪费。
懒汉式在第一次使用时才创建实例,避免了资源浪费但需要处理线程安全问题。
饿汉式单例模式的示例代码如下:
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
在这个示例代码中,Singleton 类只有一个私有的构造方法和一个公有的静态方法 getInstance()。静态变量 instance 是在类加载时就被初始化,因此在 getInstance() 方法中直接返回即可,不需要额外的同步措施。这种实现方式简单明了,线程安全,并且实现起来也比较容易。
饿汉式单例模式的缺点是在程序启动时就实例化对象,如果该单例对象需要消耗大量资源或者不经常使用,就会造成不必要的资源浪费。同时,如果该单例类有多个实例,并且其中的某个实例一直没有被使用,也会浪费内存空间。因此,在某些情况下,懒汉式单例模式可能更适合。
懒汉式单例模式示例代码:
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在该示例代码中,Singleton类只有一个私有的静态变量instance,表示类的唯一实例。该变量被声明为静态的,因此它可以被类的所有对象共享。
Singleton类的构造函数是私有的,这样就不能从外部直接实例化它。通过提供一个静态的getInstance()方法,可以获取该类的唯一实例。
在getInstance()方法中,如果instance变量为null,则通过调用构造函数创建一个新的实例,并将其赋值给instance变量。如果instance变量已经被初始化,那么直接返回它。
需要注意的是,在多线程环境下,由于getInstance()方法是同步的,可能会对性能产生负面影响,所以不推荐使用
懒汉式单例模式示例代码(双重检查):
public class Singleton {
private volatile static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
这种实现方式可以在第一次调用 getInstance() 方法时创建实例,同时保证线程安全和效率。volatile 关键字用于保证多线程环境下的可见性和有序性。在第一次检查时,多线程环境下可能会有多个线程同时通过了 instance == null 的判断,但是只有一个线程能够获取锁并创建实例,其他线程则需要等待。在锁内部再次检查 instance 是否为 null,是为了避免在释放锁之前已经有其他线程创建了实例,如果出现这种情况,则不需要再次创建实例。
单例模式常用在需要全局唯一对象的场景中,比如配置信息类、连接池类、日志记录器等。它可以保证在整个应用程序中只有一个实例存在,从而确保该实例的状态和行为在系统中保持一致。