设计模式:单例的五种实现及分析
2019-08-16 12:28:49来源:博客园 阅读 ()
设计模式:单例的五种实现及分析
????单例模式是设计模式中最简单的一种创建型模式,使用场景一般有:工具类对象、系统中只能存在一个实例对象的类、创建频繁或又耗时耗资源且又经常用到的对象等。如:JDK的Runtime类就是饥饿的单例模式,以及Spring容器管理的实例Bean默认也是饥饿单例,在容器启动时初始化,当然也可以设置为懒汉式(default-lazy-init="true")。再如程序中引入公共线程池,为防止多次创建线程池浪费资源,公共线程池也可以采用单例模式实现的。
饥饿模式
????类加载时默认初始化,实现最简单但也有一定的局限性,1、可能类加载时某些资源还未准备好,2、多个不同的自定义类加载器同时加载时可能导致重复初始化
public class HungrySingleton {
private static final HungrySingleton instance = new HungrySingleton ();
private HungrySingleton () {
// 一定要记得私有化构造器
}
public static HungrySingleton getInstance() {
return instance;
}
}
懒汉模式(要注意线程安全问题)
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton () { }
/**
* 一定要记得加synchronized
*/
public static synchronized LazySingleton getInstance() {
if(null == instance) {
instance = new LazySingleton ();
}
return instance;
}
}
双重检测锁模式
要注意线程安全隐患:多线程环境下获取到未初始化完全的实例对象,用volatile修饰对象可以防止该问题,详尽分析见下面注释
public class DoubleCheckSingleton {
/**
* TODO 这里主要利用了volatile的“顺序性”,保证对instance的写不会发生指令重排而引发其他线程获取到未初始化完全的对象
* TODO 就算没有volatile,“可见性”也可由synchronized保证
*/
private static volatile DoubleCheckSingleton instance = null;
private DoubleCheckSingleton() { }
public static DoubleCheckSingleton getInstance() {
if (null == instance) {
synchronized (DoubleCheckSingleton.class) {
if (null == instance) {
// new DoubleCheckSingleton() 不是原子操作,大体步骤如下
// memory = allocate(); // 1:分配对象的内存空间
// ctorInstance(memory); // 2:初始化对象
// instance = memory; // 3:设置instance指向刚才分配的内存地址
// 伪代码中的2和3之间,可能会被重排序,所以如果执行顺序按1,3,2的话,线程在执行完3后时间片用完切换线程则可能出现未初始化的对象
// 如果用volatile来修饰则会产生写读屏障storeload,禁止2,3的指令重拍,从而防止出现未初始化完全的问题
// TODO 就算时间片用完切换其他线程也进入不了synchronized代码块,因为原来代码块还没执行完成,所以不会释放锁,也不会出现多次实例化
instance = new DoubleCheckSingleton();
}
}
}
return instance;
}
静态内部类模式(推荐使用:由JVM保证线程安全且代码简单不容易出错)
public class InnerClassSingleton {
private InnerClassSingleton() { }
private static class NestClass {
private static final InnerClassSingleton instance = new InnerClassSingleton();
}
public static InnerClassSingleton getInstance() {
// javac编译后,NestClass是一个单独的.class文件,
// 加载InnerClassSingleton.class的时候不会自动加载NestClass.class文件
// 当调用NestClass.instance的时候才会触发JVM加载NestClass类
return NestClass.instance;
}
}
枚举模式
跟静态内部类的原理是一样的,JVM会保证enum不能被反射并且构造器方法只执行一次,因此该单例是线程安全的
public class EnumSingleton {
private EnumSingleton() { }
private enum InnerEnum {
/**
* 占位枚举值
*/
enumFactory;
private EnumSingleton instance;
/**
* TODO 注意这里是枚举类的构造器
*/
private InnerEnum() {
instance = new EnumSingleton();
}
public EnumSingleton getInstance() {
return instance;
}
}
public static EnumSingleton getInstance() {
return InnerEnum.enumFactory.getInstance();
}
}
原文链接:https://www.cnblogs.com/ocean234/p/11176954.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇:浅谈JavaWeb发展
- 设计模式-委派/策略模式 2020-06-09
- 深入理解:设计模式中的七大设计原则 2020-06-07
- 设计模式---类之间的关系知多少 2020-06-07
- 你与面试官所了解的单例模式并不一样! 2020-06-06
- Java--Java的设计模式----单例模式 2020-05-26
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash