设计模式-单例模式

单例模式的意义

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

相关推荐
小刘不想改BUG几秒前
LeetCode LCR 010 和为 K 的子数组 (Java)
java·算法·leetcode
MeyrlNotFound1 分钟前
(二十一)Java集合框架源码深度解析
java·开发语言
正在走向自律10 分钟前
2025年、2024年最新版IntelliJ IDEA下载安装过程(含Java环境搭建+Maven下载及配置)
java·jvm·jdk·maven·intellij-idea
不会就选C.10 分钟前
【开源分享】健康饮食管理系统(双端+论文)
java·spring boot·开源·毕业设计
永远有多远.11 分钟前
【高频面试题】LRU缓存
java·缓存·面试
Ten peaches12 分钟前
Selenium-Java版(环境安装)
java·前端·selenium·自动化
编程、小哥哥29 分钟前
Java求职者面试:从Spring Boot到微服务的技术点解析
java·spring boot·redis·微服务·spring security·高并发·面试题
purrrew39 分钟前
【Java ee初阶】jvm(1)
java·jvm·java-ee
Javatutouhouduan1 小时前
线上问题排查:JVM OOM问题如何排查和解决
java·jvm·数据库·后端·程序员·架构师·oom
小雅痞1 小时前
[Java][Leetcode middle] 12. 整数转罗马数字
java·linux·leetcode