这里可以添加本文要记录的大概内容:
讲解了创建型模式中的单例模式,包括单例模式在面试中常会问道的一个面试题以及它在Spring中是如何运用到的
文章不足,欢迎补充....
提示:以下是本篇文章正文内容,下面内容可供参考
一、单例模式的介绍特点:对一些重量级的对象,省略了重复创建对象花费的时间,减少了系统的开销,第二点是使用单例可以减少new *** 作的次数,减少了GC线程回收内存的压力
对于单例bean的创建方式,主要看DefaultSingletonBeanRegistry 的 getSingleton() 方法:
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { private final MapsingletonObjects = new ConcurrentHashMap<>(256); public Object getSingleton(String beanName, ObjectFactory> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { //检查缓存中是否有实例,如果缓存中有实例,直接返回 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { //省略... try { //通过singletonFactory获取单例 singletonObject = singletonFactory.getObject(); newSingleton = true; } //省略... if (newSingleton) { addSingleton(beanName, singletonObject); } } //返回实例 return singletonObject; } } protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
从源码中可以看出,是通过ConcurrentHashMap的方式,如果在Map中存在则直接返回,如果不存在则创建,并且put进Map集合中,并且整段逻辑是使用同步代码块包住的,所以是线程安全的。
能减少我们内存空间,节约性能使得性能提升:
二、懒汉模式与饿汉模式的区别 面试题:当我们和面试官聊到单例模式,面试官常会问道懒汉模式与饿汉模式的区别?以连接数据库工具类DBAccess 为例:
工具类建立一个静态的对象,放到常量区
分类:
- 饿汉式(静态常量)
- 饿汉式(静态代码块)
- 懒汉式(线程不安全)
- 懒汉式(线程安全,同步代码块)
- 懒汉式(线程安全,同步方法)
- 双重检查
- 静态内部类
- 枚举
三、单例模式在Spring中的应用懒汉模式:当我们真正需要使用对象时才去创建该单例类对象
class DBAccess6 { private DBAccess6() { } private static DBAccess6 dbAccess = null; public static DBAccess6 getInstance() { if (dbAccess == null) { synchronized (DBAccess6.class) { if (dbAccess == null) { dbAccess = new DBAccess6(); } } } return dbAccess; // return new DBAccess6(); } } class DBAccess7 { private DBAccess7() { } private static class DBAccess7Instance{ private static DBAccess7 dbAccess = new DBAccess7(); } public static DBAccess7 getInstance() { return DBAccess7Instance.dbAccess; } } enum DBAccess8{ DBACCESS; public static DBAccess8 getInstance() { return DBAccess8.DBACCESS; } }饿汉模式:在类加载时已经创建好该单例对象,等待被程序使用(巴不得别人创建好,我们直接拿过来使用)
public class DBAccess { // 构造器私有化,避免外部创建对象 private DBAccess() { } // static修饰,保障其能够被静态方法访问 private final static DBAccess dbAccess = new DBAccess(); // 外部直接调用静态方法实例化对象 public static DBAccess getInstance() { return dbAccess; } } class DBAccess2 { private DBAccess2() { } private static DBAccess2 dbAccess = null; static { dbAccess = new DBAccess2(); } public static DBAccess2 getInstance() { return dbAccess; } }结论:
单例中两种饿汉式可用,但是存在性能问题
单例中三种懒汉式不推荐,存在线程安全问题,同步方法的方式解决了线程的问题,但是性能极差
单例模式推荐用静态内部类、枚举、双重检查这三种
应用:
jdk源码中Runtime类
tomcat中ApplicationContext类
session 工厂
Spring中的JavaBean默认为单例的,bean 可以被定义为两种模式:prototype(多例)和 singleton(单例)。
- singleton(单例):只有一个共享的实例存在,所有对这个 bean 的请求都会返回唯一的实例。
- prototype(多例):对这个 bean 的每次请求都会创建一个新的 bean 实例,类似于 new。
因为SpringContext中会有很多个daoserviceaction对象;如果Bean为多例的话,就每次要用到的时候,都会重新去创建一个新的对象,内存中就会有很多重复的对象
配置文件如下:
单例模式的弊端:容易产生变量污染 总结
以上就是今天要讲的内容,本文仅仅简单介绍了单例模式以及单例模式在Spring中的体现
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)