Singleton(单例模式)

本文详细介绍了Singleton(单例模式),包括其定义、优点和缺点。讨论了饿汉模式和懒汉模式两种实现方式,并提出了优化方案,如双重检查锁定、静态内部类和使用枚举确保单例的线程安全与懒初始化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Singleton(单例模式)

介绍

  • 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

  • 解决了 一个全局使用的类频繁地创建与销毁。

优点:

  • 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例
  • 避免对资源的多重占用

缺点:

  • 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

注意:

  • 单例类只能有一个实例。
  • 单例类必须自己创建自己的唯一实例。
  • 单例类必须给所有其他对象提供这一实例。

饿汉模式(常用)

/**
 * 饿汉模式 (常用)
 *  以空间换时间  不管需不需要用到实例都要去创建实例
 *  原理:类加载到内存后,就实例化一个单例,JVM保证线程安全
 *  缺点:不管有没有用到,加载类的时候都会创建一个实例
 */
public class Mgr1 {
    private final static Mgr1 INSTANCE = new Mgr1();
    private Mgr1() {}
    public void method() {}
    public static Mgr1 getInstance() {
        return INSTANCE;
    }
    public static void main(String[] args) {
        Mgr1 m1 = Mgr1.getInstance();
        Mgr1 m2 = Mgr1.getInstance();
        System.out.println(m1==m2);
    }
}

懒汉模式

/**
 * 懒汉模式:
 * 以时间换空间  只有在用到的时候才会创建一个实例
 * 缺点: 线程不安全
 */
public class Mgr2 {
    private static Mgr2 INSTANCE;
    private Mgr2() {
    }
    public static Mgr2 getInstance() {
        if (INSTANCE == null) {
            try {
                Thread.sleep(1000);
                INSTANCE = new Mgr2();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return INSTANCE;
    }
  	 public static void main(String[] args) {
        for (int i = 0; i < 50; i++) {
            new Thread(() ->
                    System.out.println(Mgr2.getInstance().hashCode())
            ).start();
        }
    }
}

优化方案

双重判断

/**
 * 优化方式
 *      双重判断
 *  通过 synchronized 解决, 但是效率会下降
 */
public class Mgr3 {
    private static Mgr3 INSTANCE;
    private Mgr3() {}
    public static Mgr3 getInstance() {
        if (INSTANCE == null) {
            synchronized (Mgr3.class) {
                if (INSTANCE == null) {
                    try {
                        Thread.sleep(1000);
                        INSTANCE = new Mgr3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return INSTANCE;
    }
    public static void main(String[] args) {
        for (int i = 0; i < 50; i++) {
            new Thread(() ->
                    System.out.println(Mgr3.getInstance().hashCode())
            ).start();
        }
    }
}

静态内部类(懒加载)

/**
 * 优化方式:
 *   使用静态内部类
 *  JVM 会保证单例
 *  加载外部类的时候不会加载内部类,这样就实现了懒加载
 */
public class Mgr4 {
    private static class Mgr4Instance {
        public final static Mgr4 INSTANCE = new Mgr4();
    }
    public static Mgr4 getInstance() {
        return  Mgr4Instance.INSTANCE;
    }
    public static void main(String[] args) {
        for (int i = 0; i < 50; i++) {
            new Thread(() ->
                    System.out.println(Mgr4.getInstance().hashCode())
            ).start();
        }
    }
}

枚举单例

/**
 * 优化方式:枚举单例
 * 不仅可以解决线程同步,还可以防止反序列化
 */
public enum Mgr5 {
    /**
     * 实例
     */
    INSTANCE;
    public static void main(String[] args) {
        for (int i = 0; i < 50; i++) {
            new Thread(() ->
                    System.out.println(Mgr5.INSTANCE.hashCode())
            ).start();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值