📖摘要
今天分享下 —— 单例模式的 8 种写法! 的一些基本知识,欢迎关注!
单例模式即一个 JVM 内存中只存在一个类的对象实例。
🌂分类
👨懒汉式
类加载的时候就创建实例
示例1
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
线程不安全,不可用。
示例2
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
同步方法,线程安全,效率低,不推荐。
示例3
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
singleton = new Singleton();
}
}
return singleton;
}
}
线程不安全,会产生多个实例,不可用。
👨饿汉式
使用的时候才创建实例
当然还有其他的生成单例的方式,双重校验锁,枚举和静态内部类,文中会有介绍。
无线程安全问题,不能延迟加载,影响系统性能。
示例1
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
示例2
public class Singleton {
private static Singleton instance = null;
static {
instance = new Singleton();
}
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
示例3
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
双重校验锁,线程安全,推荐使用。
示例4
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
静态内部类,线程安全,主动调用时才实例化,延迟加载效率高,推荐使用。
示例5
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
💥注意事项
- 考虑多线程问题
- 单例类构造方法要设置为private类型禁止外界new创建
private Singleton() {}
- 如果类可序列化,考虑反序列化生成多个实例问题,解决方案如下
private Object readResolve() throws ObjectStreamException {
// instead of the object we're on, return the class variable INSTANCE
return INSTANCE;
}
枚举类型,无线程安全问题,避免反序列化创建新的实例,很少使用。
🚀使用场景
- 工具类对象
- 系统中只能存在一个实例的类
- 创建频繁或又耗时耗资源且又经常用到的对象
另外,
Spring
容器中的实例默认是单例饿汉式类型的,即容器启动时就实例化bean
到容器中,当然也可以设置懒汉式defalut-lazy-init="true"
为延迟实例化,用到时再实例化。
🎉最后
-
更多参考精彩博文请看这里:《陈永佳的博客》
-
喜欢博主的小伙伴可以加个关注、点个赞哦,持续更新嘿嘿!