开头说几句
博主的博客地址: https://www.jeffcc.top/
博主学习设计模式用的书是 Head First 的《设计模式》,强烈推荐配套使用!
什么是单例模式
权威定义:确保一个类只有一个实例,并提供一个全局访问点。
博主的理解:虽说单例模式对于许多人来说并不难,但是其中也是有很多需要注意的细节的。
设计方案
方案一:“急切”的单例
思路:所谓急切,是指我们在一开始的时候就创建出类的单例实例,不管有无实际需求。满足了单例设计模式的需求。
方案二 “懒汉式”单例
思路:类提供一个供对外访问的静态方法 getInstance()来对外提供一个全局访问点,然后通过私有化构造器,实现单例模式。
方案三 多线程模式
思路:通过 synchronized 关键字让 getInstance 方法变为同部方法就能轻松解决问题了
方案四 双重检查加锁的单例模式
思路:双重检查机制让方法只会第一次被锁上,以后的情况则不会出现需要同步的情况。
方案五 私有化静态内部类
回到定义
容易发现其实上面的四个单例模式的方案都是可以满足单例设计模式的要求的,至于我们又该如何做出选择,就要看具体的需求了,在确定性能以及资源的限制下,我们可以选择适合自己的单例模式,譬如如果没有什么限制,使用方案一急切式的单例模式也是可以的,但是这个直接使用全局变量的问题是,我们可能会造成在系统日渐复杂时候,用这么多的全局变量指向许多小对象会使得命名空间被“污染”;同时这个单例的控制权不在我么自己的手中,而是掌握在了 JVM 的手中。
Java 中使用到的单例模式
spirng 框架
对于最常用的 spring 框架来说,我们经常用 spring 来帮我们管理一些无状态的 bean,其默认设置为单例,这样在整个 spring 框架的运行过程中,即使被多个线程访问和调用,这些“无状态”的 bean 就只会存在一个,为他们服务。那么“无状态”bean 指的是什么呢?
- 无状态:当前我们托管给 spring 框架管理的 javabean 主要有 service、mybatis 的 mapper、一些 utils,这些 bean 中一般都是与当前线程会话状态无关的,没有自己的属性,只是在方法中会处理相应的逻辑,每个线程调用的都是自己的方法,在自己的方法栈中。
- 有状态:指的是每个用户有自己特有的一个实例,在用户的生存期内,bean 保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean 的生命期也告结束。即每个用户最初都会得到一个初始的 bean,因此在将一些 bean 如 User 这些托管给 spring 管理时,需要设置为 prototype 多例,因为比如 user,每个线程会话进来时操作的 user 对象都不同,因此需要设置为多例。
优势:
- 减少了新生成实例的消耗,spring 会通过反射或者 cglib 来生成 bean 实例这都是耗性能的操作,其次给对象分配内存也会涉及复杂算法;
- 减少 jvm 垃圾回收;
- 可以快速获取到 bean;
劣势:
单例的 bean 一个最大的劣势就是要时刻注意线程安全的问题,因为一旦有线程间共享数据变很可能引发问题。
log4j
在使用 log4j 框架时也注意到了其使用的是单例,当然也为了保证单个线程对日志文件的读写时不出问题。
END
2019 年 9 月 6 日 11:33:04
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于