Java单例模式

简介

在Java中,单例模式(Singleton Pattern)是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。单例模式通常用于需要控制资源访问的场景,比如数据库连接、线程池等。
以下是几种实现单例模式的常见方法:

1.饿汉式

类加载时创建实例:

public class Hungry {
 private volatile static Hungry instance=new Hungry();
   //构造方法私有化
    private Hungry() {}
    public static Hungry getInstance() {
        return instance;
    }
}

在这里插入图片描述
创建的类的实例为同一个

优点:创建简单,线程安全
缺点:可能浪费资源(实例在类加载时初始化,无论是否使用)

2.懒汉式单例(非线程安全)

懒汉式单例在第一次调用 getInstance() 方法时才创建实例,但这种实现方式在多线程环境下是不安全的。

  public volatile static Lazy instance=null;
    private Lazy(){};
    public  static Lazy getInstance() {
        if (instance==null) {
            synchronized (Lazy.class) {
                if (instance == null) {
                    instance = new Lazy();
                }
            }
        }
            return instance;
    }

在这里插入图片描述
缺点:在多线程环境下,可能会创建多个实例,不具备线程安全性。

3. 懒汉式单例(线程安全,同步方法)

public class Lazy2 {
    public volatile static Lazy2 instance=null;
    private Lazy2(){};

    public  static Lazy2 getInstance() {
        synchronized (Lazy2.class) {
            if (instance == null) {
                instance = new Lazy2();
            }
        }
        return instance;
    }
}

或者


```java
public class Lazy2 {
    public volatile static Lazy2 instance=null;
    private Lazy2(){};

    public synchronized  static Lazy2 getInstance() {

            if (instance == null) {
                instance = new Lazy2();
        }
        return instance;
    }
}

注意

public class Lazy2 {
    public volatile static Lazy2 instance=null;
    private Lazy2(){};

    public  static Lazy2 getInstance() {
            if (instance == null) {
              synchronized (Lazy2.class) {
                  instance = new Lazy2();
              }
        }
        return instance;
    }
}

这种写法是错误的
在这里插入图片描述
在已经进行instance是否为空的判断后再加锁,
不会产生锁冲突,线程安全问题没有解决

优点:线程安全。
缺点:每次调用 getInstance() 方法都需要进行同步,会影响性能

4.双重检查锁定(DCL)单例

就是在懒汉式(线程安全,同步方法)的基础上提前加上一次instance是否为空判断减少资源消耗

public class Lazy {
    public volatile static Lazy instance=null;
    private Lazy(){};
    public  static Lazy getInstance() {
        if (instance==null) {
            synchronized (Lazy.class) {
                if (instance == null) {
                    instance = new Lazy();
                }
            }
        }
            return instance;
    }
}

优点:线程安全,延迟加载,性能较高。
缺点:实现相对复杂。

5.静态内部类

利用类加载机制保护线程安全

public class singleton {
    private singleton(){};
    private static class Hold{
        static final singleton instacne=new singleton();
    }
    private static singleton getInstance(){
        return Hold.instacne;
    }
}

优点:线程安全,延迟加载,没有同步开销

6.枚举

public enum _enum {
INSTANCE;
}
优点:线程安全,天然防止反射和序列化攻击
缺点:不能继承其他类

7.总结

对比:
在这里插入图片描述
推荐场景:

枚举:需防止反射/序列化攻击时。
静态内部类:需延迟加载且无参数初始化时。
双重检查锁:需动态传递初始化参数时。
注意事项
反射攻击:非枚举方式需在私有构造函数中抛出异常防止多次实例化。
序列化:若单例类需序列化,应实现readResolve()方法。
设计权衡:单例模式可能引入全局状态,需谨慎使用以避免代码耦合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值