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();
    }
}

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

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

相关推荐
IT古董30 分钟前
第四章:大模型(LLM)】06.langchain原理-(3)LangChain Prompt 用法
java·人工智能·python
冷崖3 小时前
MySQL异步连接池的学习(五)
学习·mysql
知识分享小能手3 小时前
Vue3 学习教程,从入门到精通,Axios 在 Vue 3 中的使用指南(37)
前端·javascript·vue.js·学习·typescript·vue·vue3
轻抚酸~4 小时前
小迪23年-32~40——java简单回顾
java·web安全
所愿ღ4 小时前
JavaWeb-Servlet基础
笔记·servlet
岑梓铭5 小时前
考研408《计算机组成原理》复习笔记,第五章(2)——CPU指令执行过程
笔记·考研·408·计算机组成原理·计组
Sirius Wu5 小时前
Maven环境如何正确配置
java·maven
健康平安的活着6 小时前
java之 junit4单元测试Mockito的使用
java·开发语言·单元测试
Java小白程序员7 小时前
Spring Framework :IoC 容器的原理与实践
java·后端·spring
焄塰7 小时前
Ansible 管理变量和事实
学习·centos·ansible