java---单例模式

目录

前言

一、饿汉模式

1.什么是饿汉模式

2.代码展示

3.优缺点

二、懒汉模式

1.什么是懒汉模式

2.代码展示

3..注意事项

三、静态内部类

1.如何使用静态内部类

2.代码展示

四、枚举

1.如何使用枚举

2.代码展示

总结


前言

单例模式常见写法有 4 种:饿汉模式、懒汉模式、静态内部类和枚举,接下来我们一一来看。

一、饿汉模式

1.什么是饿汉模式

饿汉模式也叫预加载模式,它是在类加载时直接创建并初始化单例对象,所以它并不存在线程安全的问题。它是依靠 ClassLoader 类机制,在程序启动时只加载一次,因此不存在线程安全问题。

2.代码展示

public class StarvingMode {
    // 是线程安全的
    // 类加载的时候执行
    // JVM 保证了类加载的过程是线程安全的
    private static StarvingMode instance = new StarvingMode();

    public static StarvingMode getInstance() {
        return instance;
    }

    private StarvingMode() {}
}

3.优缺点

优点:实现简单、不存在线程安全问题。

缺点:类加载时就创建了对象,如果之后没有被使用,就造成了资源浪费的情况。

二、懒汉模式

1.什么是懒汉模式

懒汉模式与饿汉模式相反,只有在第一次被使用的时候,才会被初始化,但是这样会存在线程安全问题。

2.代码展示

public class LazyModeV3 {
    private volatile static LazyModeV3 instance = null;

    public static LazyModeV3 getInstance() {
        // 第一次调用这个方法时,说明我们应该实例化对象了
        if (instance == null) {
            // 只有 instance 还没有初始化时,才会走到这个分支
            // 这里没有锁保护,所以理论上可以有很多线程同时走到这个分支

            synchronized (LazyModeV3.class) {   // 通过上面的条件,
                                                // 让争抢锁的动作只在 instance
                                                // 实例化之前才可能发生。
                                                // 实例化之后就不再可能
                // 加锁之后才能执行
                // 第一个抢到锁的线程,看到的 instance 是 null
                // 其他抢到锁的线程,看到的 instance 不是 null
                // 保证了 instance 只会被实例化一次
                if (instance == null) {
                    instance = new LazyModeV3();    // 只在第一次的时候执行
                    // 当重排序成 1 -> 3 -> 2 的时候可能出问题
                    // 通过 volatile 修复
                }
            }
        }

        return instance;
    }

    private LazyModeV3() {}
}

3..注意事项

1.这里使用volatile修饰对象,是为了防止在实例化对象时,发生代码重排序,导致线程不安全。加上volatile关键字时,实例化对象时,不会使其代码重排序。

2.在判断if(instance == null) 时,这里会出现 check-update 场景,会导致他的原子性发生破坏,所以,使用synchronized锁,对其进行保护,以维护他的原子性,从而保证线程安全。

三、静态内部类

1.如何使用静态内部类

静态内部类既能保证线程安全,又能保证懒加载,它只有在被调用时,才会通过ClassLoader机制来加载和初始化内部静态类,因此它是线程安全的。

2.代码展示

public class Singleton {
    // 1.防止外部直接 new 对象破坏单例模式
    private Singleton() {
    }

    // 2.静态内部类
    private static class SingletonHolder {
        private static final Singleton instance = new Singleton();
    }

    // 3.提供公共获取单例对象的方法
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

四、枚举

1.如何使用枚举

枚举也是在第一次被使用时,才会被 Java 虚拟机加载并初始化,所以它也是线程安全的,且是懒加载的。

2.代码展示

public enum  EnumSingleton {
    instance;
    public EnumSingleton getInstance(){
        return instance;
    }
}

总结

单例模式适用于经常被访问的对象,或是创建和销毁需要调用大量资源和时间的对象,使用单例模式可以避免频繁创建和销毁对象。单例模式的常用实现方法有 4 种:饿汉模式、懒汉模式、静态内部类和枚举。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值