设计模式-单例模式

单例模式的意义

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

相关推荐
han_hanker12 小时前
这里使用 extends HashMap<String, Object> 和 类本身定义变量的优缺点
java·开发语言
careathers12 小时前
【JavaSE语法】面向对象初步认识
java·面向对象
coding随想12 小时前
掌控选区的终极武器:getSelection API的深度解析与实战应用
java·前端·javascript
嵌入式小能手12 小时前
飞凌嵌入式ElfBoard-文件I/O的深入学习之存储映射I/O
java·前端·学习
ChinaRainbowSea13 小时前
github 仓库主页美化定制
java·后端·github
程序猿小蒜13 小时前
基于springboot的医院资源管理系统开发与设计
java·前端·spring boot·后端·spring
程序员-周李斌13 小时前
ConcurrentHashMap 源码分析
java·开发语言·哈希算法·散列表·开源软件
ChrisitineTX13 小时前
凌晨突发Java并发问题:synchronized锁升级导致接口超时,排查过程全记录
java·数据库·oracle
zzhongcy13 小时前
Java: HashMap 和 ConcurrentHashMap的区别
java·开发语言
✎ ﹏梦醒͜ღ҉繁华落℘14 小时前
菜鸟的算法基础
java·数据结构·算法