1、关于单例模式,谈谈你的了解吧
(1)单例模式是一种常用的设计模式,单例模式比较简单但包含了关于线程安全、内存模型、类加载机制等一些比较核心的知识点。
(2)单例模式就是在整个运行时域,一个类只有一个实例对象。
(3)为什么需要单例模式呢?因为有的类型的实例对象的创建和销毁对资源来说消耗不大,比如string,然而有的类型呢就比较复杂庞大,如果频繁的创建和销毁对象并且这些对象完全是可以复用的话,那么将会造成一些不必要的性能浪费。
(4)举个例子吧,比如我现在要写一个访问数据库的demo,而创建数据库链接对象是一个耗资源的操作并且数据库链接完全是可以复用的,那么我可以将这个对象设计成单例的,这样我只要创建一次并且重复使用这个对象就可以了,而不是每次都要去访问数据库去创建一个链接对象。
2、面试中给你一张纸,手写懒加载单例模式和线程安全的单例模式
(1)懒加载单例模式:
(2)同时满足懒加载、线程安全和高性能的单例写法:
3、实现java单例模式的几种模式?
(1)饿汉式一静态常量方式(线程安全):
类加载时就初始化实例,避免了多线程同步问题,天然线程安全。
(2)饿汉式一静态代码块方式
(线程安全:其实就是在静态常量饿汉式实现上稍微变动了一下,将类的实例化放在了静态代码块中而已,其他没区别。
(3)懒汉式(线程不安全)
这是最基本的实现方式,第一次调用才初始化,实现了懒加载的特性。多线程场景下禁止使用,因为可能会产生多个对象,不再是单例。
(4)懒汉式(线程安全,方法上加同步锁)
线程不安全懒汉式实现上唯一不同是:获取实例的getInstance0方法上加了同步锁。保证了多线程场景下的单例。但是效率会有所折损,不过还好。
(5)双重校验锁(线程安全,效率高)
此种实现中不用每次需要获得锁,减少了获取锁和等待的事件。注意volatile关键字的使用,保证了各线程对singleton静态实例域修改的可见性。
(6)静态内部类实现单例(线程安全、效率高)
这种方式下Singleton类被装载了,instance不一定被初始化。因为SingletonHolder类没有被主动使用,只有通过显式调用getInstance方法时,才会显式装载SingletonHolder类,从而实例化instance.。
4、java单例模式的基本特点?
答:持有自己类型的属性:类构造器私有:对外提供获取实例的静态方法。
5、饿汉式和懒汉式的区别?
(1)线程安全方面:饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,懒汉式本身是非线程安全的。
(2)资源加载和性能方面:饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。