简介:单例模式是一种常用的设计模式,确保一个类只有一个实例,并提供一个全局访问点。本文将详细解释单例模式的饿汉式和懒汉式实现方式,并通过实例代码帮助读者理解。
单例模式是一种常见的设计模式,它的主要目的是确保一个类只有一个实例,并提供一个全局访问点。这样可以避免重复实例化对象,提高性能和资源利用率。单例模式通常用于日志记录、缓存、数据库连接等场景。
单例模式有两种常见的实现方式:饿汉式和懒汉式。下面我们将分别介绍这两种方式。
饿汉式
饿汉式是在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快。这种方式适用于线程安全的环境。
public class Singleton {// 在类加载时就完成了初始化,所以类加载比较慢private static Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}}
懒汉式
懒汉式是在第一次调用 getInstance() 方法时初始化对象,所以类加载速度快,但获取对象的速度慢。这种方式适用于多线程环境。
public class Singleton {// 类加载时不初始化private static Singleton instance;private Singleton() {}// 在第一次调用时初始化对象public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}}
需要注意的是,在多线程环境下,懒汉式可能会导致多个实例的情况,因为两个线程可能在同一时刻进入 if (instance == null) 判断语句并同时创建实例。为了避免这种情况,可以使用 synchronized 关键字进行同步,但这会降低性能。因此,通常会结合双重检查锁定(double-checked locking)机制来解决这个问题。
双重检查锁定机制的代码如下:
public class Singleton {private volatile static Singleton instance; // 使用volatile关键字保证可见性private Singleton() {}public static Singleton getInstance() {if (instance == null) { // 第一次检查实例是否为空synchronized (Singleton.class) { // 使用类对象作为锁对象,保证同一时刻只有一个线程可以进入同步块if (instance == null) { // 第二次检查实例是否为空,只有在第一次检查为空时才会进入同步块,避免了不必要的同步开销instance = new Singleton(); // 创建实例并赋值给instance变量}}}return instance; // 返回实例对象}}
通过双重检查锁定机制,我们可以在多线程环境下安全地实现单例模式,同时避免了不必要的同步开销。需要注意的是,使用 volatile 关键字可以保证可见性,即一个线程修改了 instance 变量的值后,其他线程能够立即看到修改后的值。这是因为在 Java 中,volatile 关键字可以禁止指令重排序优化,保证变量的可见性和有序性。