设计模式-单例模式

单例模式的意义

  1. 表示全局的唯一(配置类、全局计数器)
  2. 处理资源访问冲突

不同方式实现单例

单例通用构造形式

● 构造器私有化

● 提供对外接口

饿汉式

● 当类加载好的情况下就已经创建好单例,线程创建过程是安全的

● 不需要使用也会被加载,浪费内存资源

java 复制代码
public class EagerSingleton {

    private static EagerSingleton singleton=new EagerSingleton();

    private EagerSingleton() {

    }

    EagerSingleton getInstance(){
        return singleton;
    }
}

懒汉式

● 需要才会被创建加载,延迟加载

● 高并发场景下,无法保证单例的特点(通过加关键字synchronized解决)

java 复制代码
public class LazySingleton {

    private LazySingleton instance=null;

    private LazySingleton() {

    }

       LazySingleton getInstance(){
           if(instance==null){
               instance=new LazySingleton();
           }
           return instance;
       }

     /**
     * 简单的线程安全版(获得锁的时候是线程安全的)
     * 但是会降低很多并发度,实际上我们想要的是创建锁的时候线程安全 引申出双重检查锁版
     */
    public synchronized LazySingleton getInstance(){
        if(instance==null){
            instance=new LazySingleton();
        }
        return instance;
    }
}

双重检查锁

● 支持延迟加载,线程安全的实现

java 复制代码
public class DclSingleton {
    private DclSingleton instance=null;

    private DclSingleton() {

    }

    DclSingleton getInstance(){

        if(instance==null){
            synchronized (DclSingleton.class){
                if(instance==null){
                    instance=new DclSingleton();
                }
            }
        }

        return instance;
    }
}

静态内部类的实现

● 与双重检测锁一样的效果,但是通过静态内部类实现,比较简单

java 复制代码
/**
 * 静态内部类实现单例模式
 */

public class InnerSingleton {

    private InnerSingleton(){

    }

    public InnerSingleton getInstance(){
        return SingletonHolder.instance;
    }

    /**
     * 当外部类被加载的时候,静态内部类不会被加载
     * 只有调用getInstance,SingletonHolder 才会被加载,才会创建单例
     */

    static class SingletonHolder{
        private static final InnerSingleton instance=new InnerSingleton();
    }
}

枚举

● 枚举特性就是保证了唯一性和线程安全性,实现相对比较简单

java 复制代码
public enum GlobalCounter {
    INSTANCE;
    private  AtomicInteger atomicInteger=new AtomicInteger(0);

    public long getNumber(){
        return atomicInteger.incrementAndGet();
    }
}

单例模式破坏

● 反射入侵(通过反射得到构造器,再创建实例)

● 序列化与反序列化(会破坏单例特点)

源码应用

JDK中的Runtime.class

单例存在的问题

  1. 无法支持面向对象编程(OOP 的三大特性是封装、继承、多态。单例将构造私有化,直接导致的 结果就是,他无法成为其他类的父类,这就相当于直接放弃了继承和多态的特性。
  2. 极难的拓展性(业务拓展,单例逐渐需要变得多例,比如数据库连接池可能根据数据库的类型不同有不同的连接池)

不同作用范围下的单例

线程级别的单例

● 单例一般是进程级别的,实现一个线程级别的单例几个思路

● TheardLocal就是线程级别的单例,保持每个线程独立,可以再里面进行读写东西

● spring中的RequestContextHolder,可以再一个线程中轻松的获取 request、response和session。

容器级别的单例

● 从进程切换到一个容器管理,利用spring强大的容器管理对象的整个生命周期,确保单例的特点

相关推荐
长安有故里y5 分钟前
tomcat设置预防host头攻击
java·tomcat·firefox
生产队队长6 分钟前
Tomcat问题:启动脚本startup.bat中文乱码问题解决
java·ajax·tomcat
张紫娃18 分钟前
idea 常用快捷键
java·ide·intellij-idea
兮动人22 分钟前
Java应用全链路故障排查实战指南:从系统资源到JVM深度诊断
java·开发语言·jvm
风流 少年30 分钟前
Cursor创建Spring Boot项目
java·spring boot·后端
wáng bēn37 分钟前
【java17】使用 Word 模板导出带替换符、动态表格和二维码的文档
java·word·itextpdf
贱贱的剑1 小时前
2.单例模式
单例模式·设计模式
全栈凯哥2 小时前
16.Spring Boot 国际化完全指南
java·spring boot·后端
M1A12 小时前
Java集合框架深度解析:LinkedList vs ArrayList 的对决
java·后端
Top`2 小时前
Java 泛型 (Generics)
java·开发语言·windows