一、单例模式
本文最后更新于 976 天前,其中的信息可能已经有所发展或是发生改变。

解决的问题

  • 有些数据在系统中只应该保存一份,比如系统的配置信息类
  • 资源访问冲突的问题,比如多个logger写入同一个日志文件

几种实现方式

饿汉式

  • 静态成员变量,类加载时实例化

  • 线程安全

  • 不支持延迟加载

public class HungryManDemo {

    private static final HungryManDemo instance = new HungryManDemo();

    private HungryManDemo() {}

    public static HungryManDemo getInstance(){
        return instance;
    }
}

懒汉式

  • 支持延迟加载

  • 不支持高并发

    image-20210804111822457

public class LazyManDemo {

    private static LazyManDemo instance;

    private LazyManDemo() {}

    public static LazyManDemo getInstance() {
        if (instance == null) {
            instance = new LazyManDemo();
        }
        return instance;
    }
}

懒汉式——双重检查

  • 支持高并发

  • 支持延迟加载

  • 使用volatile,禁止指令重排序

  • 在双重检测时可使用局部变量优化,减少访问volatile修饰的变量,以提升性能

  • 实现复杂

public class LazyManDoubleCheckDemo {

    private static volatile LazyManDoubleCheckDemo instance;

    private LazyManDoubleCheckDemo() {}

    public static LazyManDoubleCheckDemo getInstance() {
        LazyManDoubleCheckDemo temp = instance;
        if (temp == null) {
            synchronized (LazyManDoubleCheckDemo.class) {
                temp = instance;
                if (temp == null) {
                    temp = new LazyManDoubleCheckDemo();
                    instance = temp;
                }
            }
        }
        return instance;
    }
}

静态内部类

  • 支持延迟加载

  • 支持高并发

  • 实现比双重检测简单

  • SingletonClass没有static的属性,因此并不会被初始化。直到调用getInstance()的时候,会首先加载SingletonClassInstance类,这个类有一个static的SingletonClass实例,因此需要调用SingletonClass的构造方法,然后getInstance()将把这个内部类的instance返回给使用者。由于这个instance是static的,因此并不会构造多次。

    由于SingletonClassInstance是私有静态内部类,所以不会被其他类知道,同样,static语义也要求不会有多个实例存在。并且,JSL规范定义,类的构造必须是原子性的,非并发的,因此不需要加同步块。同样,由于这个构造是并发的,所以getInstance()也并不需要加同步。

image-20210804111908133

public class StaticInnerClassDemo {

    private StaticInnerClassDemo() {}

    private static class SingletonHolder{
        private static final StaticInnerClassDemo instance = new StaticInnerClassDemo();
    }

    public static StaticInnerClassDemo getInstance() {
        return SingletonHolder.instance;
    }
}

枚举

  • 不支持延迟加载

  • 支持高并发

  • 实现最简单

  • 使用枚举除了线程安全和防止反射调用构造器之外,还提供了自动序列化机制,防止反序列化的时候创建新的对象。因此,《Effective Java》作者推荐使用的方法。

public enum EnumDemo {
    INSTANCE;
}

序列化问题

反序列化会产生新对象,违反单例规则

解决方案:JVM从内存中反序列化地"组装"一个新对象时,会自动调用类的readResolve方法,我们可以通过此方法返回指定好的对象。

public class SerialProblem {

    private static volatile SerialProblem instance;

    private SerialProblem() {}

    public static SerialProblem getInstance() {
        SerialProblem temp = instance;
        if (temp == null) {
            synchronized (SerialProblem.class) {
                temp = instance;
                if (temp == null) {
                    temp = new SerialProblem();
                    instance = temp;
                }
            }
        }
        return instance;
    }

    private Object readResolve() {
        return instance;
    }
}

反射问题

反射获取构造器,进行实例化产生新对象

解决方案:第二次实例化的时候,抛出异常

public class ReflectProblem {

    private static volatile ReflectProblem instance;

    private ReflectProblem() {
        Assert.isNull(instance);
    }

    public static ReflectProblem getInstance() {
        ReflectProblem temp = instance;
        if (temp == null) {
            synchronized (ReflectProblem.class) {
                temp = instance;
                if (temp == null) {
                    temp = new ReflectProblem();
                    instance = temp;
                }
            }
        }
        return instance;
    }
}
作者:Yuyy
博客:https://yuyy.info

评论

  1. Yuyy
    博主
    Windows Chrome
    3年前
    2021-9-03 16:52:24

    JDK源码里JRELocaleProviderAdapter维护的LocaleProvider全是单例,使用的是DCL,volatile


    查看图片
    image-20210903144157438

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇