当前位置: 首页 > article >正文

三、《重学设计模式》-单例模式

单例模式

单例模式分为四大类,饿汉式、懒汉式、静态内部类、枚举

饿汉式

优点:类装载时进行实例化,避免同步问题

缺点:造成内存浪费

实现一

1.构造器私有化

2.内部创建对象实例

3.提供静态方法

public class Type1 {
    public static void main(String[] args) {
        SingleTon1 instance = SingleTon1.getInstance();
        SingleTon1 instance1 = SingleTon1.getInstance();
        System.out.println(instance == instance1);
        System.out.println(instance.hashCode());
        System.out.println(instance1.hashCode());
    }
}

class SingleTon1{
    // 加载实例化
    private static  final SingleTon1 instance = new SingleTon1();

    private SingleTon1(){}

    public static SingleTon1 getInstance(){
        return instance;
    }
}

实现二

1.构造器私有化

2.静态变量

3.静态代码块初始化

public class Type2 {

    public static void main(String[] args) {
        SingleTon2 instance = SingleTon2.getInstance();
        SingleTon2 instance1 = SingleTon2.getInstance();
        System.out.println(instance == instance1);
        System.out.println(instance.hashCode());
        System.out.println(instance1.hashCode());
    }
}

class SingleTon2{
    private static SingleTon2 instance;

    private SingleTon2(){}

    // 静态块
    static {
        instance = new SingleTon2();
    }

    public static SingleTon2 getInstance(){
        return instance;
    }
}

懒汉式

方案一(线程不安全)

1.静态变量

2.构造函数私有化

3.静态方法调用时创建实例

public class Type3 {

    public static void main(String[] args) {
        SingleTon3 instance = SingleTon3.getInstance();
        SingleTon3 instance1 = SingleTon3.getInstance();
        System.out.println(instance == instance1);
        System.out.println(instance.hashCode());
        System.out.println(instance1.hashCode());
    }
}

class SingleTon3 {
    private static SingleTon3 instance;

    private SingleTon3() {
    }


    public static SingleTon3 getInstance() {
        if (instance == null) {
            instance = new SingleTon3();
        }
        return instance;
    }
}

方案二(线程安全同步锁)

1.静态变量

2.构造函数私有化

3.静态方法调用时加synchronized同步锁,创建实例

缺点:效率低

public class Type4 {

    public static void main(String[] args) {
        SingleTon4 instance = SingleTon4.getInstance();
        SingleTon4 instance1 = SingleTon4.getInstance();
        System.out.println(instance == instance1);
        System.out.println(instance.hashCode());
        System.out.println(instance1.hashCode());
    }
}

class SingleTon4 {
    private static SingleTon4 instance;

    private SingleTon4() {
    }

    // 同步锁,所有线程阻塞排队 
    public static synchronized SingleTon4 getInstance() {
        if (instance == null) {
            instance = new SingleTon4();
        }
        return instance;
    }
}

方案三(同步代码块,线程不安全, 不能用、不能用、不能用)

public class Type5 {

    public static void main(String[] args) {
        SingleTon5 instance = SingleTon5.getInstance();
        SingleTon5 instance1 = SingleTon5.getInstance();
        System.out.println(instance == instance1);
        System.out.println(instance.hashCode());
        System.out.println(instance1.hashCode());
    }
}

class SingleTon5 {
    private static SingleTon5 instance;

    private SingleTon5() {
    }


    public static  SingleTon5 getInstance() {
        if (instance == null) {
            // 同步代码块,但是有两个线程同时进入if判断,就会创建多个实例
            synchronized (Type5.class){
                instance = new SingleTon5();
            }
        }
        return instance;
    }
}

方案四(双重检查)

优点:线程安全、懒加载、效率高

public class Type6 {

    public static void main(String[] args) {
        SingleTon6 instance = SingleTon6.getInstance();
        SingleTon6 instance1 = SingleTon6.getInstance();
        System.out.println(instance == instance1);
        System.out.println(instance.hashCode());
        System.out.println(instance1.hashCode());
    }
}

class SingleTon6 {
    private volatile static  SingleTon6 instance;

    private SingleTon6() {
    }

    public static  SingleTon6 getInstance() {
        if (instance == null) {
            synchronized (Type5.class){
                if(instance == null){
                    instance = new SingleTon6();
                }
            }
        }
        return instance;
    }
}

静态内部类

静态内部类特点,外部类装载时,内部类不会被装载

调用静态方法时,装载静态内部类,线程安全

静态内部类中定义静态变量

优点:静态内部类实现了延迟加载,线程安全有jvm控制

public class Type7 {

    public static void main(String[] args) {
        SingleTon7 instance = SingleTon7.getInstance();
        SingleTon7 instance1 = SingleTon7.getInstance();
        System.out.println(instance == instance1);
        System.out.println(instance.hashCode());
        System.out.println(instance1.hashCode());
    }
}

class SingleTon7 {
    private SingleTon7() {
    }

    private static class SingleTon7Holder {
        private static final SingleTon7 INSTANCE = new SingleTon7();
    }

    public static SingleTon7 getInstance() {
        return SingleTon7Holder.INSTANCE;
    }
}
枚举

避免线程不安全,防止反序列化重新创建新对象

public class Type8 {

    public static void main(String[] args) {
        SingleTonEnum.INSTANCE.whateverMethod();
    }
}


enum SingleTonEnum {
    INSTANCE;

    public void whateverMethod() {
        System.out.println("hhh");
    }
}
举例

JDK 中 RunTime

在这里插入图片描述

总结

1.频繁创建或销毁的对象适合使用单例模式

2.创建对象耗时过长或者资源过多适合使用单例模式

3.频繁用到的对象,类似工具类等,适合使用单例模式


http://www.kler.cn/a/560169.html

相关文章:

  • Python - 代码片段分享 - Excel 数据实时写入方法
  • uniapp打包生产证书上架IOS全流程
  • 【PDF预览】使用iframe实现pdf文件预览,加盖章
  • Redis7——基础篇(七)
  • JDK安装步骤
  • 机器人学习模拟框架 robosuite 支持强化学习和模仿学习 (1) 快速入门
  • 使用 LROPoller 处理 Azure 文档分析时的常见问题及解决方案
  • 猿创征文 【高级篇】Java 进阶之JVM实战
  • MATLAB中fft函数用法
  • 数据结构与算法-图论-最短路-单源最短路的建图方式
  • 从vue底层原理上解释ref和reactive的区别
  • 【NLP 24、实践 ⑤ 计算Bert模型中的参数数量】
  • 2024年国赛高教杯数学建模D题反潜航空深弹命中概率问题解题全过程文档及程序
  • 网络安全产品
  • 数据安全_笔记系列02:国密算法(商用密码算法)详解
  • 测试工程师玩转DeepSeek之Prompt
  • 为什么java从json中获取值有数据类型,而从xml中获取值没有数据类型?
  • vue3学习4-pinia+组件通信
  • python与C系列语言的差异总结(2)
  • Apache Doris:一款高性能的实时数据仓库