为什么要使用单例模式
单例的优点
1.只有一个实例,节省开销
2.全局使用方便,同时避免频繁创建和销毁
使用单例的注意点:
要避免造成 内存泄漏
常用的单例模式
单例不仅要满足线程安全,还要注意防止序列化产生新对象。如果单例实现了Serializable接口,就必须加入如下方法(枚举单例不用这么做,因为JVM能保障这点):
private Object readResolve() throws ObjectStreamException{ return INSTANCE;
}原文链接
更多教程
饿汉式
饿汉式:就是在类初始化时就实例化,所以是线程安全的。
缺点是:
1.没有懒加载,在不需要的时候也会被实例化,造成内存浪费。
2.实例化方法对外部调用不友好,传参不方便
public class Singleton implements Serializable { private static final Singleton INSTANCE = new Singleton(); // 私有化构造函数
private Singleton(){} public static Singleton getInstance(){ return INSTANCE;
} /**
* 如果实现了Serializable, 必须重写这个方法
*/
private Object readResolve() throws ObjectStreamException { return INSTANCE;
}
}懒汉式
延迟加载(使用时加载),节省内存
双重判空,第一次判空防止重复加锁,第二次判空才实例化
防止DCL指令重拍序,加volatile关键字
public class Singleton { private volatile static Singleton INSTANCE; //声明成 volatile
private Singleton (){} public static Singleton getSingleton() { if (INSTANCE == null) {
synchronized (Singleton.class) { if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
} return INSTANCE;
}
}//如果实现了Serializable, 必须重写同上面饿汉式一样的readResolve方法枚举式
由JVM保证线程安全
序列化和反射攻击已经被枚举解决
//enum枚举类public enum Singleton {
INSTANCE;
public void yourMethod() {
}
}内部类实现单例
当Singleton被加载时,其内部类并不会被初始化,故可以确保当 Singleton类被载入JVM时,不会初始化单例类。只有 getInstance() 方法调用时,才会初始化 instance。同时,由于实例的建立是时在类加载时完成,故天生对多线程友好,getInstance() 方法也无需使用同步关键字。
public class Singleton {
/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例没有绑定关系,
* 而且只有被调用到才会装载,从而实现了延迟加载
*/
private static class SingletonHolder{
/**
* 静态初始化器,由JVM来保证线程安全
*/
private static final Singleton instance = new Singleton();
}
/**
* 私有化构造方法
*/
private Singleton(){
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
作者:TryEnough
链接:https://www.jianshu.com/p/4c38969ef2ff
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦