准备换工作面试时,被问到了,突然卡壳,羞愧的无地自容,老程序员的我懵逼了。
-
什么是单例模式:
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例 -
为什么要用单例:单例模式解决了类实例生成个数的问题,
2.1:对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销;
2.2:由于new操作的次数减少,所以系统内存的使用评率也会降低,这将减少GC压力,缩短GC停顿时间。
2.3:解决多线程并发访问问题 -
为什么不用静态:一个全局的静态变量并不能保证没有其他实例被创建
-
单例的核心:
4.1:将构造函数私有化;
4.2:通过静态方法获取唯一一个实例; -
单例的创建方式:
5.1:饿汉式:直接创建那个唯一实例 无论是否需要;(线程安全,调用率高,但是,不能延迟加载。)
public class UserInfo {
//static 类加载就创建该类的对象
private static UserInfo demo =new UserInfo();
//构造方法私有化,外部不能直接创建对象
private UserInfo(){
}
//提供一个公共方法返回对象,提供一个对象提取点
public static UserInfo getInstance(){
return demo;
}
}
5.2:懒汉式:再需要时再创建那个唯一实例;(线程安全,调用效率不高,可以延时加载。)
public class UserInfo {
private static volatile UserInfo mUserInfo;
//私有化构造方法
private UserInfo() {
}
/**
* 提供静态方法 让外界获取到对象
* 需要线程安全 加锁synchronized 这个锁针对的是静态方法 而不是实例
* 故实例需要加上volatile修饰,来保证实例不是空的
* 即使加锁也不安全,要加个volatile关键字才可以,原因如下:
* 虚拟机会有一个指令重排序机制导致的:可能会先赋予对象地址 然后再初始化
* https://blog.youkuaiyun.com/weixin_42120550/article/details/117759813
*
* @return
*/
public static synchronized UserInfo getInstance() {
if (mUserInfo == null) {
mUserInfo = new UserInfo();
}
return mUserInfo;
}
}
5.3:静态内部类式(线程安全,调用效率高。但是,可以延时加载)
public class UserInfo {
//定义静态内部类
private static class signInstance{
private static UserInfo sn =new UserInfo();
}
//私有化构造器
private UserInfo(){
}
//调用内部类方法得到对象
public static UserInfo getInstance(){
return signInstance.sn;
}
}
5.4:枚举式(线程安全,调用率高,不能延时加载)
- 各种模式优缺点:
——单例对象 占用资源少,不需要 延时加载
枚举式 好于 饿汉式
——单例对象 占用资源大,需要延时加载
静态内部类式 好于 懒汉式