单例模式需要注意的地方:
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。
单例类必须给所有其他对象提供这一实例。
参考菜鸟教程的设计模式单例模式
1、懒汉式,线程不安全
public class Singleton {
//私有静态此对象,那此对象如果存在只能存在一个,由静态来决定的
private static Singleton instance;
//私有构造方法,不让调用者new
private Singleton (){}
//单线程没问题,多线程不行,因为有可能在前一个还没创建的时候另一个线程也进去了
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2、懒汉式,线程安全
public class Singleton {
//私有静态对象
private static Singleton instance;
//私有构造函数
private Singleton (){}
//加了一个synchronized 独占锁,防止上面的情况发生 ,更像悲观锁
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3、饿汉式,线程安全
public class Singleton {
//自己new出来了此对象,并且是静态的,那只能存在一个此对象
private static Singleton instance = new Singleton();
//私有构造方法
private Singleton (){}
//谁用此对象就返回已经创建好的静态的此对象
public static Singleton getInstance() {
return instance;
}
}
4、双检锁/双重校验锁,线程安全
public class Singleton {
//公共可见此静态对象,用了关字volatile
private volatile static Singleton singleton;
//私有化构造方法
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
// synchronized(类的名.class)是全局锁,不管有几个对象就公用一把锁,更像乐观锁
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
5、登记式/静态内部类,线程安全
public class Singleton {
//内部静态类
private static class SingletonHolder {
//静态最终不可变的INSTANCE,实例化父对象
private static final Singleton INSTANCE = new Singleton();
}
//私有构造方法
private Singleton (){}
//final,该方法被锁定,可以防止任何继承类修改它的意义和实现;
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
这个实现懒加载的方式是有Singleton 不一定有此对象的实例化,当调用getInstance才实例化内部类,在调用内部类创建父类的实例对象(这个内部类只能由Singleton 调用,外部是不能调用的),还是不可变的,说明实例化一次后,以后调用的都是第一次实例化的
6、枚举,线程安全
//简单但是不好理解
//描述::这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
菜鸟上的评价:
一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。
自己的感觉:感觉第4种双检锁挺好理解的,而且性能又这么好,为什么不一开始就直接用双检锁机制呢,还能忽略一些细节,因为它都满足了
————————————————
版权声明:本文为CSDN博主「胖墩的IT」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43113679/article/details/99291545