欤夤 发表于 2025-6-9 06:25:41

学习笔记-设计模式-创建型模式-单例模式

单例模式

一个类只有一个实例,并提供一个全局访问此实例的点,哪怕多线程同时访问。
单例模式主要解决了一个全局使用的类被频繁的创建和消费的问题。
单例模式的案例场景


[*]数据库的连接池不会反复创建
[*]spring中一个单例模式bean的生成和使用
[*]在我们平常的代码中需要设置全局的一些属性保存
七种单例模式的实现

1.懒汉模式(线程不安全,懒加载)

public static class Singleton_01 {
    private static Singleton_01 instance;
   
    private Singleton_01() {}
   
    public static Singleton_01 getInstance() {
      if (null != instance) {
            return instance;
      }
      instance = new Singleton_01();
      return instance;
    }
}非常标准且简单地单例模式。
满足了懒加载,但是线程不安全。
2.懒汉模式(线程安全,懒加载)

public static class Singleton_02 {
    private static Singleton_02 instance;
   
    private Singleton_02() {}
   
    public static synchronized Singleton_02 getInstance() {
      if (null != instance) {
            return instance;
      }
      instance = new Singleton_02();
      return instance;
    }
}线程安全,但是效率低,不建议使用。
3.饿汉模式(线程安全)

public class Singleton_03 {
    private static Singleton_03 instance = new Singleton_03();
   
    private Singleton_03() { }
   
    public static Singleton_03 getInstance() {
      return instance;
    }   
}饿汉模式,在程序启动的时候直接运行加载。
4.使用内部静态类(线程安全、懒加载)

public class Singleton_04 {
    private static class SingletonHolder {
      private static Singleton_04 instance = new Singleton_04();
    }
   
    private Singleton_04() { }
   
    public static Singleton_04 getInstance() {
      return SingletonHolder.instance;
    }
}通过内部静态类实现了懒加载和线程安全,推荐使用。
5.锁+双重校验(线程安全,懒加载)

private class Singleton_05 {
    private static volatile Singleton_05 instance;
   
    private Singleton_05() { }
   
    public static Singleton_05 getInstance() {
      if (null != instance) {
            return instance;
      }
      synchronized (Singleton_05.class) {
            if (null == instance) {
                instance = new Singleton_05();
            }
      }
      return instance;
    }
}相较于线程安全的懒汉模式,这种方法效率更高。
6.CAS【AtomicReference】(懒加载,线程安全)

public class Singleton_06 {
    private static final AtomicReference<Singleton_06> INSTANCE = new AtomicReference<Singleton_06>();
   
    private Singleton_06() {}
   
    public static final Singleton_06 getInstance() {
      for(;;) {
            Singleton_06 instance = INSTANCE.get();
            if (null != instance) {
                return instance;
            }
            INSTANCE.compareAndSet(null, new Singleton_06());
            return INSTANCE.get();
      }
    }
}AtomicReference可以封装引用一个V实例,支持并发访问。
使用CAS的好处就是不需要使用传统的加锁方式保证线程安全,而是依赖于CAS的忙等算法,依赖于底层硬件的实现,来保证线程安全。相对于其他锁的实现,没有线程的切换和阻塞,也就没有了额外的开销,并且可以迟迟较大的并发性。
但CAS的一个缺点就是忙等,如果一直没有获取到将会处于死循环中。
7.枚举单例(线程安全)

public enum Singleton_07 {
   
    INSTANCE;
   
    private Map<String, String> cache = new ConcurrentHashMap<>();

    public Map<String, String> getCache() {
      return cache;
    }

    public void addToCache(String key, String value) {
      cache.put(key, value);
    }
}《Effective Java》作者推荐使用枚举的方式解决单例模式,这种方法解决了线程安全、自由串行化和单一实例的问题。
调用时也很方便:Singleton_07.INSTANCE.getCache();
枚举单例十分简洁,并且它无常地提供了串行化机制,绝对防止对此实例化(毕竟是枚举)。
但是它在继承的场景下是不可使用的,并且不是懒加载(毕竟是枚举)。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

翁真如 发表于 2025-12-15 11:27:20

感谢发布原创作品,程序园因你更精彩

矛赓宁 发表于 2025-12-31 05:16:15

感谢分享,学习下。

金娅鸣 发表于 2026-1-16 06:37:35

东西不错很实用谢谢分享

昝沛珊 发表于 2026-1-20 00:11:30

这个有用。

劳暄美 发表于 2026-1-21 00:07:39

过来提前占个楼

厨浴 发表于 2026-1-21 19:29:23

很好很强大我过来先占个楼 待编辑

拙因 发表于 2026-1-21 22:18:58

这个有用。

匣卒 发表于 2026-1-23 07:54:23

谢谢分享,试用一下

指陡 发表于 2026-1-24 09:58:53

不错,里面软件多更新就更好了

裴竹悦 发表于 2026-1-25 11:56:18

过来提前占个楼

科元料 发表于 2026-1-28 08:54:07

收藏一下   不知道什么时候能用到

廖彗云 发表于 2026-1-28 16:27:53

前排留名,哈哈哈

怒鼓踊 发表于 2026-1-29 02:59:21

前排留名,哈哈哈

炳裘垦 发表于 2026-2-1 05:49:37

用心讨论,共获提升!

赘暨逢 发表于 2026-2-4 07:51:28

前排留名,哈哈哈

呵桢 发表于 2026-2-5 10:36:07

东西不错很实用谢谢分享

裒噎 发表于 2026-2-6 08:51:19

谢谢分享,试用一下

扔飒 发表于 2026-2-6 21:53:48

懂技术并乐意极积无私分享的人越来越少。珍惜

玲液 发表于 2026-2-7 08:01:56

感谢分享,学习下。
页: [1] 2
查看完整版本: 学习笔记-设计模式-创建型模式-单例模式