你能看懂的设计模式之单例模式
2021/5/22 18:57:05
本文主要是介绍你能看懂的设计模式之单例模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章目录
- 前言
- 单例模式
- 1.定义
- 2.特点
- 3.优缺点
- 4.应用场景
- 实现方式
- 1.懒汉模式 (线程不安全)
- 2.懒汉模式 (线程安全)
- 3.饿汉模式 (线程安全)
- 4.使用类的内部类 (线程安全)
- 5.双重锁校验 (线程安全)
- 6.CAS (线程安全)
- 7.枚举单例 (线程安全)
- 总结
前言
作者目前在复习总结设计模式,便计划写一个设计模式的专题,本篇介绍的是单例模式,主要介绍的是7种单例模式的实现。作者写博客主要是为了归纳总结技术,加深对它的理解,如有任何错误地方请帮忙指出。
单例模式
1.定义
单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。
2.特点
- 单例类只有一个实例对象;
- 该单例对象必须由单例类自行创建;
- 单例类对外提供一个访问该单例的全局访问点。
3.优缺点
优点:
- 单例模式可以保证内存里只有一个实例,减少了内存的开销。
- 可以避免对资源的多重占用。
- 单例模式设置全局访问点,可以优化和共享资源的访问。
缺点:
- 单例模式一般没有接口,扩展困难。
- 在并发测试中,单例模式不利于代码调试。
- 单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。
4.应用场景
- 需要频繁创建的一些类,使用单例可以降低系统的内存压力,减少 GC。
- 某类只要求生成一个对象的时候,如每个人的身份证号等。
- 某些类创建实例时占用资源较多,或实例化耗时较长,且经常使用。
- 某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。
5.当对象需要被共享的场合。
实现方式
1.懒汉模式 (线程不安全)
/** * 懒汉模式 (线程不安全) * @author winter */ public class Singleton_01 { private static Singleton_01 instance; private Singleton_01() { } public static Singleton_01 getInstance(){ if (null != instance) { return instance; } return new Singleton_01(); } }
特点:不能再外部创建,也就是new Singleton_01()。
问题:线程不安全,多个访问者同时获取对象实例,就会造成多个同样的实例并存。
2.懒汉模式 (线程安全)
/** * 懒汉模式 (线程安全) * @author winter */ public class Singleton_02 { private static Singleton_02 instance; private Singleton_02() { } public static synchronized Singleton_02 getInstance() { if (null != instance) { return instance; } return new Singleton_02(); } }
线程安全,直接将锁加在方法上,所有的访问都会抢锁占用,导致资源浪费,效率低,不推荐。
3.饿汉模式 (线程安全)
/** * 饿汉模式 (线程安全) * @author winter */ public class Singleton_03 { private static Singleton_03 instance = new Singleton_03(); private Singleton_03() { } public static Singleton_03 getInstance() { return instance; } }
在启动时候直接运行加载,后续有外部需要使用时直接获取即可,会造成一些内存浪费问题。
4.使用类的内部类 (线程安全)
/** * 使用类的内部类 (线程安全) * @author winter */ 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.双重锁校验 (线程安全)
/** * 双重锁校验 (线程安全) * @author winter */ public class Singleton_05 { private static 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 (线程安全)
/** * CAS (线程安全) * @author winter */ public class Singleton_06 { private static final AtomicReference<Singleton_06> INSTANCE = new AtomicReference<Singleton_06>(); private static Singleton_06 instance; 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(); } } }
在线程竞争不激烈时,相对其他锁的实现,没有线程的切换和阻塞也没有了额外的开销,并且可以支持较大的并发。但在在线程竞争激烈时,CAS会一直自旋。
7.枚举单例 (线程安全)
/** * 枚举单例 (线程安全) * @author winter */ public enum Singleton_07 { INSTANCE; public void doSomething() { System.out.println("doSomething"); } //调用方式 public static void main(String[] args) { Singleton_07.INSTANCE.doSomething(); } }
这种方式解决了线程安全、自由穿行化和单一实例问题,并且非常简洁,是Joshua.J.Bloch推荐的单例模式。
总结
单例是设计模式中最简单的一种模式,但在各种的实现上却需要用到java的基本功,也是面试中高频率问到一种设计模式,如 1. 请写出一种高效安全的单例模式? 2. 懒汉模式是线程安全吗?为什么?
参考 《重新java设计模式》
这篇关于你能看懂的设计模式之单例模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南