设计模式-单例模式
单例模式是指一个类在整个进程中只有一个实例化的对象,后续对该类的实例化都将调用已经创建好的第一个实例化对象,常用在重量级的对象中,比如sqlsession等
单例模式有好几种写法,饿汉模式,懒汉模式
//单例模式的饿汉模式,即还没调用该对象的时候,就创建实例, public class hungry { //利用类的静态变量存放在jvm的静态方法区的性质 private static hungry hungrys=new hungry(); //私有的无参构造函数,令外界无法new一个对象 private hungry(){ System.out.println("懒汉模式构造了函数"); } public static hungry getHungrys(){ return hungrys; } }
对该函数进行两次调用,发现构造函数只打印了一次,说明对象只实例化了一次,
//懒汉模式,只有当第一个实例化对象的时候才会创建出来 public class lazy { private static lazy lazys=null; private lazy(){ }
//只有在调用该方法时才会产生一个对象
//只有lazys为空的时候才会给他分配一个对象,不然直接返回,在多线程时不安全,需要加锁 .为了线程安全,不产生多个对象,对单例进行两次判空,如果只进行一次判空当两个线程同时到达锁的位置,会进行两次实例化
public static lazy getInstance(){
if (lazys == null)
synchronized (lazy.class)
{
if (lazys == null)
lazys = new lazy(); }
return lazys; } }
懒汉模式,重点在于加锁,懒汉模式是线程不安全的,需要进行加锁,并且加锁后还要进行一次空的判断。为避免cpu优化指令序列,指令重排后会导致空指针异常,还要加上violate关键字,使指令按顺序执行,指令重排主要发生在新建对象时,会有两条底层指令,分别是类的初始化,以及将类的地址赋值给lazys变量,jvm指令重排可能会先将地址赋值给变量,再进行初始化,那么这个时候有进程获取singoleton对象时,会返回还未初始化的对象导致错误。
在方法上加锁称为简单懒汉式,在获取对象时加锁称为DCL双重检验加锁,静态内部类也是懒汉模式的一种,但是一定线程安全。
//静态内部类实现懒汉模式,一定线程安全 class innerLazy{ static class inner{ private final static innerLazy innerLazys=new innerLazy(); } //只有调用方法时才会加载类,把内部类的静态变量放到虚拟区 public static innerLazy getInstance() { return inner.innerLazys; } } }
枚举:
public enum Singleton { INSTANCE; } 调用方法: public class Main { public static void main(String[] args) {
Singleton.INSTANCE
} } 直接通过Singleton.INSTANCE.doSomething()的方式调用即可。方便、简洁又安全。
懒汉和饿汉都是通过构造器的私有化来保证外界无法构造实例,但是实际上可以通过反射机制直接获得类的构造器,并不安全,可以在构造器进行一次判空处理,如果当前对象不为空时抛出异常,而enum是无法通过反射获得其构造器的,所以是安全的
反序列化也会对单例模式造成破坏,反序列获得的对象,其构造器不是从类中获得,拥有其自己的方法,可以通过重写readresolve来实现,直接返回当前的对象
readResolve:如果被反序列化的对象的类存在readResolve这个方法,他会调用这个方法来返回一个“array”,然后浅拷贝一份,作为返回值,并且无视掉反序列化的值,即使那个字节码已经被解析。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix