设计模式-单例模式

单例模式的意义

  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强大的容器管理对象的整个生命周期,确保单例的特点

相关推荐
一个网络学徒2 分钟前
python5
java·服务器·前端
workflower6 分钟前
业务需求-假设场景
java·数据库·测试用例·集成测试·需求分析·模块测试·软件需求
专注VB编程开发20年24 分钟前
vb.net datatable新增数据时改用数组缓存
java·linux·windows
(>_<)27 分钟前
java minio 分片上传工具类与测试demo
java·minio·分片上传
不想打工的码农27 分钟前
MyBatis-Plus多数据源实战:被DBA追着改配置后,我肝出这份避坑指南(附动态切换源码)
java·后端
Coder_Boy_43 分钟前
Deeplearning4j+ Spring Boot 电商用户复购预测案例
java·人工智能·spring boot·后端·spring
踢足球09291 小时前
寒假打卡:2026-2-7
java·开发语言·javascript
闻哥1 小时前
Kafka高吞吐量核心揭秘:四大技术架构深度解析
java·jvm·面试·kafka·rabbitmq·springboot
金牌归来发现妻女流落街头1 小时前
【Springboot基础开发】
java·spring boot·后端
考琪1 小时前
Nginx打印变量到log方法
java·运维·nginx