设计模式-单例模式

单例模式的意义

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

相关推荐
未来可期LJ20 分钟前
【C++ 设计模式】单例模式的两种懒汉式和饿汉式
c++·单例模式·设计模式
Dola_Pan1 小时前
Linux文件IO(二)-文件操作使用详解
java·linux·服务器
wang_book1 小时前
Gitlab学习(007 gitlab项目操作)
java·运维·git·学习·spring·gitlab
蜗牛^^O^2 小时前
Docker和K8S
java·docker·kubernetes
从心归零3 小时前
sshj使用代理连接服务器
java·服务器·sshj
IT毕设梦工厂4 小时前
计算机毕业设计选题推荐-在线拍卖系统-Java/Python项目实战
java·spring boot·python·django·毕业设计·源码·课程设计
Ylucius4 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
七夜zippoe5 小时前
分布式系统实战经验
java·分布式
是梦终空5 小时前
JAVA毕业设计176—基于Java+Springboot+vue3的交通旅游订票管理系统(源代码+数据库)
java·spring boot·vue·毕业设计·课程设计·源代码·交通订票
落落落sss5 小时前
sharding-jdbc分库分表
android·java·开发语言·数据库·servlet·oracle