Java设计模式/创建型模式/单例模式

发布于:2022-12-22 ⋅ 阅读:(161) ⋅ 点赞:(0)

介绍

方式 特点 对比
饿汉式 类加载阶段创建,多线程安全 简单快速
懒汉式-普通 延迟到运行创建单例,多线程安全,懒加载 直接方法加锁
懒汉式-DCL 2次检查+1把锁,多线程安全,懒加载 检查之后再加锁,比普通懒汉式快
枚举 反序列化安全,多线程安全 反序列化安全
  • 一般效率高使用饿汉式,有懒加载要求使用懒汉式,保证反序列化单例使用枚举式,有特殊要求使用DCL(Double Check Lock)
  • 单例模式需要保证在“”多线程“”,“反序列化”情况下依旧单例
  • 饿汉式类加载阶段创建单例,懒汉式运行阶段创建单例
  • static变量可以保证多线程情况下依旧单例
  • enum变量可以保证反序列化情况下依旧单例

应用

  • spring IOC容器,向外提供单例对象

优点

  • 内存中只有一个实例,减少了内存的开销,避免了对象频繁的被创建或销毁

代码

饿汉式

本代码实现特点:

  • 多线程单例
  • 饿汉式
  • 性能高

补充知识

  • static变量(无final修饰)在验证-准备阶段分配空间并默认初始化
  • <clinit>()方法(类初始化方法)中执行static变量(无final修饰)的初始化
  • <clinit>()方法只在类的首次主动使用时被1个线程执行一次(是线程安全的)

hungry/SingletonXcrj

public class SingletonXcrj {
    // 静态成员属性直接赋值,饿汉式,初始化阶段为singletonXcrj有且赋值1次,保证单例且饿汉
    private static SingletonXcrj singletonXcrj = new SingletonXcrj();

    // 私有化构造器并且不对外提供setter,getter,不允许new SingletonXcrj()
    private SingletonXcrj() {

    }

    // 静态方法操作静态变量,直接返回属性中创建的单例对象
    public static SingletonXcrj getSingleton() {
        return SingletonXcrj.singletonXcrj;
    }
}

hungry/Main

public class Main {
    public static void main(String[] args) {
        SingletonXcrj singletonXcrj = SingletonXcrj.getSingleton();
    }
}

懒汉式-普通

本代码特点

  • 多线程单例
  • 懒汉式
  • 性能比DCL低

lazy/SingletonXcrj

public class SingletonXcrj {
    // 静态成员属性,未赋值
    private static SingletonXcrj singletonXcrj;

    // 私有化构造器并且不对外提供setter,getter,不允许new SingletonXcrj()
    private SingletonXcrj() {

    }

    // 静态方法操作静态变量,synchronized 保证多线程单例
    public static synchronized SingletonXcrj getSingleton() {
        return SingletonXcrj.singletonXcrj = new SingletonXcrj();
    }
}

lazy/Main

public class Main {
    public static void main(String[] args) {
        SingletonXcrj singletonXcrj = SingletonXcrj.getSingleton();
    }
}

懒汉式DCL-Double Check Lock

介绍

  • 为了提高普通懒汉式的速度

本代码特点

  • 双重检查+1把所
  • 多线程单例

dcl/SingletonXcrj

public class SingletonXcrj {
    // 静态成员属性,未赋值
    // volatile关键字保证 变量的可见性和有序性
    private volatile static SingletonXcrj singletonXcrj;

    // 私有化构造器并且不对外提供setter,getter,不允许new SingletonXcrj()
    private SingletonXcrj() {
    }

    // 静态方法操作静态属性
    public static SingletonXcrj getSingleton() {
        // 第1重检查
        if (SingletonXcrj.singletonXcrj == null) {
            // 加锁,再检查
            synchronized (SingletonXcrj.class) {
                // 第2重检查
                if (SingletonXcrj.singletonXcrj == null) {
                    return SingletonXcrj.singletonXcrj = new SingletonXcrj();
                }
            }
        }

        return SingletonXcrj.singletonXcrj;
    }
}

dcl/Main

public class Main {
    public static void main(String[] args) {
        SingletonXcrj singletonXcrj = SingletonXcrj.getSingleton();
    }
}

枚举式

介绍

  • 反序列化单例
  • 多线程单例
  • 枚举式过程:类的主动使用,导致类加载阶段执行()方法调用私有化的构造方法初始化SINGLETON静态变量
    补充知识
  • 枚举量默认public static final
  • 枚举构造函数默认private
  • 反序列化安全,编译器不允许任何对枚举序列化机制的定制操作

enums/SingletonHolder

/*
 * 过程:
 * 类的主动使用,导致类加载阶段执行<clinit>()方法调用私有化的构造方法初始化SINGLETON静态变量
 * */
public enum SingletonHolder {
    // 枚举量默认public static final
    SINGLETON;
    private SingletonResource singletonResource;

    // 枚举构造函数默认private
    SingletonHolder() {
        this.singletonResource = new SingletonResource();
        System.out.println("1234");
    }

    // 未要求静态方法
    public SingletonResource getSingletonResource() {
        return SINGLETON.singletonResource;
    }
}

enums/SingletonResource

public class SingletonResource {
    public void SayHi(){
        System.out.println("hi, I am singleton!");
    }
}

enums/Main

public class Main {
    public static void main(String[] args) {
        SingletonResource singletonResource=SingletonHolder.SINGLETON.getSingletonResource();
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到