设计模式--单例模式(Singleton pattern)及应用
单例模式
- 参考文档:
- 菜鸟教程单例模式介绍了单例模式的6种实现
- 该文仅介绍spring的单例模式:spring 的单例模式
- 介绍原理:Spring的单例模式底层实现
- 参考书籍:漫谈设计模式:从面向对象开始-刘济华.pdf
1. 单例模式解析
- 单例所指的就是单个实例,也就是说要保证一个类仅有一个实例。
- 单例模式有以下的特点:
- ①单例类只能有一个实例
- ②单例类必须自己创建自己的唯一实例
- ③单例类必须给所有其他对象提供这一实例
2. 单例模式示例
- 以下示例都是在同一个JVM中实现的,在分布式环境下如何保证分布在不同机器上的整个应用只有一个实例是更复杂的话题。
2.1 简单单例模式
- 为了实现上面的特点,有以下基本实现:
/**
* 单例模式示例:
* - 简单单例模式
*/
public class Singleton{
//变量是私有的,外界无法访问
private static Singleton singleton = new Singleton();
//other fields...
//Singleton类只有一个构造方法,被private修饰的, 客户对象无法创建该类实例。
private Singleton(){
}
//实现全局访问点
public static Singleton getInstance(){
return singleton;
}
//other motheds...
}
- 如果该实例需要比较复杂的初始化过程时,可以把这个过程应该写在static{……}代码块中
- 此实现是线程安全的,当多个线程同时去访问该类的getInstance( ) 方法时,不会初始化多个不同的对象,这是因为,JVM在加载此类时,对于static属性的初始化只能由一个线程执行且仅一次。
2.2 延迟创建的单例模式
- 上面的单例模式会在类加载的时候就初始化实例,如果这样的单例较多,会使程序初始化效率低下。
- 为了在类的实例第一次使用时才初始化,我们可以把单例的实例化过程放到getInstance()方法中,而不在加载类时预先创建。
/**
* 单例模式示例:
* - 延迟创建的单例模式
*/
public class UnThreadSafeSingleton{
//变量是私有的,外界无法访问
private static UnThreadSafeSingleton singleton = null;
//other fields...
//UnThreadSafeSingleton类只有一个构造方法,被private修饰的, 客户对象无法创建该类实例。
private UnThreadSafeSingleton(){
}
//实现全局访问点
public static UnThreadSafeSingleton getInstance(){
//在这里实现延迟创建,但是下面的三行不是线程安全的,
//在高并发环境下会生成多个不同的该类实例
//在没有自动内存回收机制的语言平台中,容易内存泄露
if(singleton ==null){
singleton = new UnThreadSafeSingleton();
}
return singleton;
}
//other motheds...
}
- 为了解决上面线程安全的问题,我们可以给此方法加synchronized关键字,来保证多线程访问都只会实例化一次。
Double-Check Locking
- 为了提高并发性能,可以只对上面导致线程不安全的三行代码进行同步
- 参考:java中volatile关键字的含义
/**
* 单例模式示例:
* - 线程安全的延迟创建的单例模式
*/
public class DoubleCheckSingleton{
//变量是私有的,外界无法访问
//volatile具有synchronized的可见性特点,也就是说线程能够自动发现volatile变量的最新值。
//这样,如果instatnce实例化成功,其他线程便能立即发现
private volatile static DoubleCheckSingleton singleton = null;
//other fields...
//DoubleCheckSingleton类只有一个构造方法,被private修饰的, 客户对象无法创建该类实例。
private DoubleCheckSingleton(){
}
//实现全局访问点
public static DoubleCheckSingleton getInstance(){
//两次检查是为了防止两个线程都进行到同步块的时候,可能会创建两个实例
if(singleton ==null){
synchronized (DoubleCheckSingleton.class){
if(singleton ==null){ //这里如果不检查还是会生成两个实例
singleton = new DoubleCheckSingleton();
}
}
return singleton;
}
//other motheds...
}
2.3 Initialization on demond holder
- 另一种实现延迟加载且线程安全的实例化方法
/**
* 单例模式示例:
* - 延迟加载单例模式
*/
public class LazyLoadedSingleton{
//other fields...
//LazyLoadedSingleton类只有一个构造方法,被private修饰的, 客户对象无法创建该类实例。
private LazyLoadedSingleton(){
}
private static class LazyHolder{
//变量是私有的,外界无法访问
//holds zhe singleton class
private static LazyLoadedSingleton singleton = new LazyLoadedSingleton();
}
/**
* 只有当第一次调用该方法时,JVM才会加载LazyHolder类,然后才初始化static的singleton
* 这样即保证了线程安全,又实现了延迟加载
*/
public static LazyLoadedSingleton getInstance(){
return LazyHolder.singleton;
}
//other motheds...
}
2. spring的单例模式
- 参考文档:
- 该文仅介绍spring的单例模式:spring 的单例模式
- 介绍原理:Spring的单例模式底层实现
- 对spring中单例模式线程安全的讨:Spring中Singleton模式的线程安全
- 针对上面的单例模式有以下说法:
- 延迟加载的单例模式可以称为懒汉式单例
- 非延迟加载的称为饿汉式单例
- 饿汉式单例在自己被加载时就将自己实例化,如果从资源利用效率角度来讲,比懒汉式单例类稍差些。但是从速度和反应时间角度来讲,则比懒汉式要稍好些。
- 解释参考文档上的一句话:由于构造函数是私有的,因此该类不能被继承
- 上面的单例模式都不能被继承,所以spring采用的是另一种单例模式,称为单例注册表
2.1 单例注册表方法
- Spring对单例的底层实现,到底是饿汉式单例还是懒汉式单例呢?呵呵,都不是。Spring框架对单例的支持是采用单例注册表的方式进行实现的。
- 以下参考文章分析的源代码应该是spring比较老的版本,我参考现在比较新的4.3.2版本,有些不同,但是原理应该是一样的。下面的源代码是spring-beans-4.3.2-REALEASE版本的。
- 详情参考:Spring的单例模式底层实现
- Spring对bean实例的创建是采用单例注册表的方式进行实现的,而这个注册表的缓存是HashMap对象,如果配置文件中的配置信息不要求使用单例,Spring会采用新建实例的方式返回对象实例
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
......
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
.....
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
//对传入的Bean name稍做处理,防止传入的Bean name名有非法字符(或者做转码)
final String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
//从单例注册表中查找,如果存在,就获得了单例
if(sharedInstance != null && args == null) {
......
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
......
//否则
try {
//取得bean的定义
final RootBeanDefinition ex1 = this.getMergedLocalBeanDefinition(beanName);
......
//如果是单例,做如下处理
if(ex1.isSingleton()) {
sharedInstance = this.getSingleton(beanName, new ObjectFactory() {
...... });
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, ex1);
} else if(ex1.isPrototype()) {
......
//如果是prototype。创建一个bean
Object var25;
try {
this.beforePrototypeCreation(beanName);
var25 = this.createBean(beanName, ex1, args);
} finally {
this.afterPrototypeCreation(beanName);
}
......
bean = this.getObjectForBeanInstance(var25, name, beanName, ex1);
} else {
......
bean = this.getObjectForBeanInstance(var28, name, beanName, ex1);
}
} catch (BeansException var23) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var23;
}
}
if(requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
......
} else {
return bean;
}
}
设计模式--单例模式(Singleton pattern)及应用的更多相关文章
- 浅谈设计模式--单例模式(Singleton Pattern)
题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...
- 设计模式之单例模式(Singleton Pattern)
单例模式 单例模式(Singleton Pattern)在java中算是最常用的设计模式之一,主要用于控制控制类实例的数量,防止外部实例化或者修改.单例模式在某些场景下可以提高系统运行效率.实现中的主 ...
- 乐在其中设计模式(C#) - 单例模式(Singleton Pattern)
原文:乐在其中设计模式(C#) - 单例模式(Singleton Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 单例模式(Singleton Pattern) 作者:weba ...
- 设计模式系列之单例模式(Singleton Pattern)——确保对象的唯一性
模式概述 模式定义 模式结构图 饿汉式单例与懒汉式单例 饿汉式单例 懒汉式单例 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 主要优点 适用场景 说明:设计模式系列文章是读刘伟所著 ...
- 【设计模式】单例模式 Singleton Pattern
通常我们在写程序的时候会碰到一个类只允许在整个系统中只存在一个实例(Instance) 的情况, 比如说我们想做一计数器,统计某些接口调用的次数,通常我们的数据库连接也是只期望有一个实例.Windo ...
- 二十四种设计模式:单例模式(Singleton Pattern)
单例模式(Singleton Pattern) 介绍保证一个类仅有一个实例,并提供一个访问它的全局访问点. 示例保证一个类仅有一个实例. Singleton using System; using S ...
- 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)
在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...
- 十次艳遇单例设计模式(Singleton Pattern)
1.引言 单例设计模式(Singleton Pattern)是最简单且常见的设计模式之一,在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访 ...
- 设计模式 单例模式(Singleton) [ 转载2 ]
设计模式 单例模式(Singleton) [ 转载2 ] @author java_my_life 单例模式的结构 单例模式的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类 ...
- 设计模式 单例模式(Singleton) [ 转载 ]
设计模式 单例模式(Singleton) [ 转载 ] 转载请注明出处:http://cantellow.iteye.com/blog/838473 前言 懒汉:调用时才创建对象 饿汉:类初始化时就创 ...
随机推荐
- FLAnimatedImageView处理gif过程
FLAnimatedImageView处理gif过程 时间控制原理 GIF图片每一帧的delayTime可能都不一样: 在展示下一帧的时间控制机制,不能根据以第一帧为准: 或总动画时长除以帧数来简单做 ...
- php面向对象1
类和对象的关系 首先看一段代码 var_dump()后的结果 注意 一个对象系统自动分配一个对象标识符!
- jsp中怎么调用java类中的方法
在jsp页面中先要,引入java类 例如: <%@page import="javabean.DbConn"%><!-- 引入包中的"类" - ...
- lvs之 lvs原理架构介绍
一. 概念 lvs的术语: Router:GWIP vs:virtual server,director rs:real server CIP:client IP VIP:virtual server ...
- 活动页怎么切图photoshop
一 切固定大小的单个图片 1.用pc打开图像 2.按ctrl+A(全选) 3.点击 选择 ->变换选区 ->拉参考线(把参考线放到最中央)->按回车 ->ctrl+d(取消全选 ...
- Spring事务管理—aop:pointcut expression解析
先来看看这个spring的配置文件的配置: <!-- 事务管理器 --> <bean id="transactionManager" class="o ...
- 反射+自定义注解---实现Excel数据列属性和JavaBean属性的自动映射
简单粗暴,直奔主题. 需求:通过自定义注解和反射技术,将Excel文件中的数据自动映射到pojo类中,最终返回一个List<pojo>集合? 今天我只是通过一位使用者的身份来给各位分享 ...
- mybatis if test 解决页面 升序和降序的问题
<if test="status !=null and status !='' and status =='1'.toString()"> ORDER BY tag.c ...
- Vulkan Tutorial 22 Index buffer
操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 在实际产品的运行环境中3D模型的数据往往共享多个三角形之间 ...
- 【LeetCode】67. Add Binary
题目: Given two binary strings, return their sum (also a binary string). For example,a = "11" ...