JUC并发编程——单例模式(基于狂神说的学习笔记)

单例模式

饿汉式:

java 复制代码
package single;

// 饿汉式单例
public class hungry {

    // 饿汉式有可能会浪费内存
    // 因为饿汉式在生成对象时,就创建了所有的空间
    // 单例模式构造器私有
    private hungry(){

    }

    private final static hungry HUNGRY = new hungry();
    public static hungry getInstance(){
        return HUNGRY;
    }
}

普通懒汉式:

java 复制代码
package single;

// 懒汉式单例模式
public class lazy {

    // 单例模式构造器私有
    private lazy(){
        System.out.println(Thread.currentThread().getName()+" gotten");
    }

    // 普通懒汉式,在并发下可能会出现问题
    private static lazy lazyMan;
    public static lazy getInstance(){
        if (lazyMan == null){
            lazyMan = new lazy();
        }
        return lazyMan;
    }


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

}

使用synchronized与volatile的懒汉式单例

java 复制代码
package single;

// 懒汉式单例模式
public class lazy {
    
    // 单例模式构造器私有
    private lazy(){
        System.out.println(Thread.currentThread().getName()+" gotten");
    }

    // 双重检测锁模式的懒汉式单例
    private volatile static lazy lazyMan;
    private static lazy getInstance(){
        if(lazyMan == null){
            synchronized(lazy.class){
                if (lazyMan == null){
                    lazyMan = new lazy();// 不是一个原子性操作
                    /**
                     * 1、分配内存空间
                     * 2、执行构造方法,初始化对象
                     * 3、把这个对象指向这个空间
                     * 该过程可能发生指令重排
                     * 因此必须让对象加volatile生成内存屏障
                     */
                }
            }
        }
        return lazyMan;
    }

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

}

静态内部类

java 复制代码
package single;

// 静态内部类  (不安全)
public class Holder {

    // 单例模式构造器私有
    private Holder(){

    }
    public static Holder getInstance(){
        return InnerClass.HOLDER;
    }
    public static class InnerClass{
        private static final Holder HOLDER = new Holder();
    }
}

以上单例都不安全,使用反射即可破坏单例

使用枚举单例模式,反射无法破坏枚举单例

相关推荐
刘白Live8 分钟前
【Java】谈一谈浅克隆和深克隆
java
一线大码10 分钟前
项目中怎么确定线程池的大小
java·后端
要加油哦~12 分钟前
vue · 插槽 | $slots:访问所有命名插槽内容 | 插槽的使用:子组件和父组件如何书写?
java·前端·javascript
crud15 分钟前
Spring Boot 3 整合 Swagger:打造现代化 API 文档系统(附完整代码 + 高级配置 + 最佳实践)
java·spring boot·swagger
天天摸鱼的java工程师21 分钟前
从被测试小姐姐追着怼到运维小哥点赞:我在项目管理系统的 MySQL 优化实战
java·后端·mysql
周某某~32 分钟前
四.抽象工厂模式
java·设计模式·抽象工厂模式
Camellia031138 分钟前
嵌入式学习--江协stm32day5
stm32·嵌入式硬件·学习
a_1571532498642 分钟前
SpringCloud学习笔记-4
笔记·学习·spring cloud
异常君1 小时前
高并发数据写入场景下 MySQL 的性能瓶颈与替代方案
java·mysql·性能优化
烙印6011 小时前
MyBatis原理剖析(二)
java·数据库·mybatis