定义:是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。
适用场景:
确保任何情况下都只有一个实例。
如:要求生产唯一序列号。
WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
优点:
在内存中只有一个实例,减少了内存开销。
可以避免对资源的多重占用。
设置全局访问点,严格控制访问。
缺点:
没有接口,拓展困难。
如果要拓展单例对象,只有修改代码,没有其他途径。
常见写法:
1、饿汉式单例:在单例类首次加载时就创建
优点:执行效率高、性能高、没有任何的锁
缺点:某些情况下,可能会造成内存浪费
2、懒汉式单例:被外部类调用时才创建实例
优点:节省了内存
缺点:方法不加锁线程不安全,只加synchronized会造成性能瓶颈(用双重检查)
3、注册式单例:将每一个实例都缓存到统一的容器中,使用唯一标识获取实例
分为枚举式单例和容器式单例;
4、ThreadLocal单例:保证线程内部的全局唯一,且天生线程安全
注意:
反序列化会通过反射调用无参数的构造方法创建一个新的对象;只要在Singleton类中定义readResolve就可以解决该问题:private Object readResolve() { return singleton; }
源码应用:
1)一些资源配置注解标记的类产生的对象,如@Resource、@Autowired、@Bean、@Configuration等
2)spring在单例模式下使用ApplicationContext.getBean获取单例对象