深入浅出设计模式——单例模式(Java实现)

设计模式当中的单例模式想必是大家耳熟能详的了,或多或少都有些了解,但未必了解的全,在这里我总结了一共7种单例模式,仅供大家参考。

饿汉式

类加载到内存后,就实例化一个单例,JVM保证线程安全
简单实用,推荐使用
唯一缺点:不管用到与否,类加载时就完成实例化

main方法是为了测试类是否是单例

/**
 * @author baskbull
 * @date 2021/5/18 13:40
 * 饿汉式
 * 类加载到内存后,就实例化一个单例,JVM保证线程安全
 * 简单实用,推荐使用
 * 唯一缺点:不管用到与否,类加载时就完成实例化
 */
public class Singleton1 {
    //只会初始化一次
    private static final Singleton1 INSTANCE = new Singleton1();

    private Singleton1() {
    }

    public static Singleton1 getInstance() {
        return INSTANCE;
    }

    public static void main(String[] args) {
        Singleton1 singleton1 = Singleton1.getInstance();
        Singleton1 singleton2 = Singleton1.getInstance();
        //true
        System.out.println(singleton1 == singleton2);

    }
}

饿汉式(静态代码块)

/**
 * @author baskbull
 * @date 2021/5/18 13:45
 * 本质上和1没区别
 */

    private static final Singleton2 INSTANCE;
    //只会初始化一次
    static {
        INSTANCE = new Singleton2();
    }

    private Singleton2() {
    }


    public static Singleton2 getInstance() {
        return INSTANCE;
    }

    public static void main(String[] args) {
        Singleton2 singleton1 = Singleton2.getInstance();
        Singleton2 singleton2 = Singleton2.getInstance();
        //true
        System.out.println(singleton1 == singleton2);
    }

懒汉式

lazy loading
懒汉式
虽然达到了按需初始化的目的,但却带来线程不安全的问题

/**
 * @author baskbull
 * @date 2021/5/18 18:59
 * lazy loading
 * 懒汉式
 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题
 */
public class Singleton3 {
    private static Singleton3 INSTANCE;

    private Singleton3(){}

    private static Singleton3 getInstance(){
        if(INSTANCE == null){
            INSTANCE = new Singleton3();
        }
        return INSTANCE;
    }
}

懒汉式(加锁解决线程不安全问题)

lazy loading
懒汉式
虽然达到了按需初始化的目的,但却带来线程不安全的问题
可以通过synchronized解决,但也带来效率下降

/**
 * @author baskbull
 * @date 2021/5/18 18:59
 * lazy loading
 * 懒汉式
 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题
 * 可以通过synchronized解决,但也带来效率下降
 */
public class Singleton4 {
    private static Singleton4 INSTANCE;

    private Singleton4(){}

    private static synchronized Singleton4 getInstance(){
        if(INSTANCE == null){
            INSTANCE = new Singleton4();
        }
        return INSTANCE;
    }
}

饿汉式(不可行,原因在main函数中)

/**
 * @author baskbull
 * @date 2021/5/18 18:59
 * lazy loading
 * 懒汉式
 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题
 * 可以通过synchronized解决,但也带来效率下降
 */
public class Singleton5 {
    private static Singleton5 INSTANCE;

    private Singleton5(){}

    private static Singleton5 getInstance(){
        if(INSTANCE == null){
            //尝试通过减小同步代码块的方式来提高效率,不可行
            synchronized (Singleton5.class){
                INSTANCE = new Singleton5();
            }

        }
        return INSTANCE;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                System.out.println(Singleton5.getInstance().hashCode());
            }).start();
        }
    }
}

双重校验锁实现单例

/**
 * @author baskbull
 * @date 2021/5/18 18:59
 * lazy loading
 * 懒汉式
 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题
 * 可以通过synchronized解决,但也带来效率下降
 */
public class Singleton6双重校验 {
    private static volatile Singleton6双重校验 INSTANCE;

    private Singleton6双重校验() {
    }

    private static Singleton6双重校验 getInstance() {
        //双重检查
        if (INSTANCE == null) {
            synchronized (Singleton6双重校验.class) {
                if (INSTANCE == null) {
                    INSTANCE = new Singleton6双重校验();
                }
            }

        }
        return INSTANCE;
    }
}

静态内部类实现单例

静态内部类方式
jvm保证单例
加载外部类时不会加载内部类,这样可以实现懒加载

/**
 * @author baskbull
 * @date 2021/5/18 18:59
 * 静态内部类方式
 * jvm保证单例
 * 加载外部类时不会加载内部类,这样可以实现懒加载
 */
public class Singleton7静态内部类 {

    private Singleton7静态内部类() {
    }

    private static class Singleton7Holder{
        private final static Singleton7静态内部类 INSTANCE = new Singleton7静态内部类();
    }

    private static Singleton7静态内部类 getInstance(){
        return Singleton7Holder.INSTANCE;
    }
}

枚举

在大家为单例的实现争论不休的时候,Java的创始人在《Effective Java》中推荐使用枚举来实现单例

不仅可以解决线程同步,还可以解决反序列化
枚举类没有构造方法

这个虽然看着别扭,但就是这么简单~

/**
 * @author baskbull
 * @date 2021/5/18 18:59
 * 不仅可以解决线程同步,还可以解决反序列化
 * 枚举类没有构造方法
 */
public enum Singleton8枚举 {
    INSTANCE;
}

好了,单例模式就到这里,下一篇来讲策略模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值