单例模式
保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
常见的应用场景:
任务管理器。回收站。网站的计数器。操作系统的文件系统。在servlet编程中,每个servlet也是单例模式,项目中,读取配置文件的类,一般也只有一个对象,数据库的连接池,Application对象等。
优点:
由于单例模式只生成一个实例,减少了系统开销,当一个对象的产生需要比较多的资源时,如读取配置文件,产生其他资源对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决
常见的五种单例模式的实现方式:
饿汉式(线程安全,调用效率高,但是不能延时加载)
懒汉式(线程不安全,调用效率不高,但是可以延时加载)
其他:
双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题,不建议使用)
静态内部类式(线程安全,调用效率高,但是可以延时加载)
枚举单例(线程安全,调用效率高,不能延时加载)
比较
饿汉式和懒汉式区别
1、线程安全:
饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,懒汉式本身是非线程安全的,为了实现线程安全有几种写法
2、资源加载和性能:
饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。
单例一定就只会创建一个对象吗?不一定。
如果有两个类加载器加载了该单例类,则就可能会创建多个单例实例。
每个类加载器都定义了一个命名空间,如果有两个以上的类加载器,不同的类加载器有可能会加载同一个类,如果多个类加载器同时加载了该单例类,就有可能创建多个单例对象。
如果有这种情况,我们应该自行指定类加载器,并指向同一个类加载器。