【单例模式】java实现
概述:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
关键点:
- 构造函数不对外开放,一般为private。
- 通过一个静态方法或者枚举返回单例类对象。
- 确保单例类的对象有且只有一个,尤其在多线程情况下。
- 确保单例类对象在反序列化时不会重新构建对象
(1)饿汉模式
饿汉式单例模式(在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快)
public class EagerSingle {
//饿汉模式单例
//在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快
private static EagerSingle single = new EagerSingle();//静态私有成员,已初始化
private EagerSingle() {
//私有构造函数
}
public static EagerSingle getInstance() {//静态,不用同步(类加载时已初始化,不会有多线程的问题)
return single;
}
}
(2)懒汉模式
懒汉模式声明一个静态对象,并且在用户第一次调用getInstance时进行初始化。
public class LazySingleton {
//懒汉模式单例
//比较懒,在类加载时不创建实例,因此类加载熟读快,但运行时获取对象速度慢
private static LazySingleton instance;//静态私有成员,没有初始化
private LazySingleton() {
//私有构造函数
}
public static synchronized LazySingleton getInstance() {//静态、同步、公开访问
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
synchronized关键字保证了同步,在多线程情况下单例的唯一性。
存在问题:即使instance已经存在,每次调用getInstance依然会进行同步,这样就会消耗不必要的资源。
总结:懒汉模式的优点是只有在使用时才会实例化单例对象,在一定程度上节约了资源;缺点是第一次加载时需要进行实例化,反应稍慢;最大问题是每次调用都会进行同步吗,造成不必要的同步开销。这种模式一般不建议使用。
(3)Double Check Lock(DCL)双重校验锁
DCL方式实现单例的优点是既能在需要时才初始化单例,又能保证线程安全,且单例对象初始化后调用getInstance不进行同步锁。
public class DCLSingleton {
//Double Check Lock单例模式
//懒汉模式的改进
//但仍然存在隐患
private static DCLSingleton instance = null;
private DCLSingleton() {
}
public static DCLSingleton getInstance() {
if (instance == null) {//第一层判断主要是为了避免不必要的同步
synchronized (DCLSingleton.class) {
if (instance == null) {//第二层判空是为了在null情况下创建实例
instance = new DCLSingleton();
}
}
}
return instance;
}
}
亮点在getInstance方法上,有两次判空。第一层判断主要是为了避免不必要的同步,第二层判空是为了在null情况下创建实例。
- 执行下面这行代码
single = new Singleton();
实际上并不是一个原子操作,这句代码实际做了3件事
- 给Singleton的实例分配内存;
- 调用Singleton()的构造函数,初始化成员字段
- 将instance对象指向分配的内存空间(此时instance已经不是null了)
问题:但由于java编译器允许处理器乱序执行,上述顺序2、3是不能保证的,可能是1-2-3也可能是1-3-2;如果是后者,3执行了已经非空,再走2会出现问题,这就是DCL失效。
解决: volatile关键字
// private static DCLSingleton instance = null;
private volatile static DCLSingleton instance = null;
只需要加上volatile关键字,如上述代码操作就可以保证instance对象每次都是从主内存中读取的,就可以采用DCL来完成单例模式了。当然,volatile或多或少会影响到性能,但考虑到程序的正确性,牺牲点性能还是值得的。
总结:
- 优点:资源利用率高,第一次执行getInstance时单例对象才会被实例化,效率高。
- 缺点:第一次加载时反应稍慢;由于java内存模型的原因偶尔会失败,在高并发环境下也有一定的缺陷,虽然概率很小。
- DCL模式是使用最多的单例实现方式
(4)静态内部类单例模式
public class InnerSingleton {
private InnerSingleton() {
}
public static InnerSingleton getInstance() {
return InnerSingletonHolder.instance;
}
/**
* 静态内部类
*/
private static class InnerSingletonHolder {
private static final InnerSingleton instance = new InnerSingleton();
}
}
总结:第一次加载InnerSingleton类时并不会初始化instance,只有在第一次调用InnerSingleton的getInstance方法时才会导致instance被初始化。因此,第一次调用getInstance方法会导致虚拟机加载InnerSingleton类,这种方法不仅能保证线程安全,也能够保证单例对象的唯一性,同时也延迟了单例的实例化,所以这也是一种推荐的单例模式实现方法
(5)枚举单例
public enum EnumSingleton {
INSTANCE;
public void doSomething() {
//do sth ...
}
}
震惊?没错!就是枚举!
- 写法简单;枚举在java种与普通类是一样的,不仅能够有字段,还能够有自己的方法。最重要的是默认枚举实例的创建时线程安全的,并且在任何情况下都是一个单例。
- 为什么这么说呢? 在上述的集中单例模式实现种,在一个情况下他们都会出现重新创建对象的情况,那就是反序列化。
补充: 通过序列化可以将一个单例的实例对象写到磁盘,然后再读回来,从而有效的获取一个实例。即使构造函数是私有的,反序列化时依然可以通过特殊的途径去创建类的一个新的实例,相当于调用该类的构造函数。
【单例模式】java实现的更多相关文章
- 单例模式——Java EE设计模式解析与应用
单例模式 目录: 一.何为单例 二.使用Java EE实现单例模式 三.使用场景 一.何为单例 确保一个类只有一个实例,并且提供了实例的一个全局访问点 1.1 单例模式类图 ...
- 单例模式——java设计模式
单例模式 目录: 一.何为单例 二.使用Java EE实现单例模式 三.使用场景 一.何为单例 确保一个类只有一个实例,并且提供了实例的一个全局访问点 1.1 单例模式类图 ...
- 设计模式 -- 单例模式(Java&&PHP)
所谓单例模式,简单来说,就是在整个应用中保证只有一个类的实例存在.就像是Java Web中的application,也就是提供了一个全局变量,用处相当广泛,比如保存全局数据,实现全局性的操作等. 能够 ...
- 枚举类型的单例模式(java)
Inspired by Effective Java. Singleton模式是在编程实践中应用最广泛的几种设计模式之一.以前知道的,实现单例的方法有两种(下面的A.B).刚刚在读<Effect ...
- 单例模式--java代码实现
单例模式 单例模式,顾名思义,在程序运行中,实例化某个类时只实例化一次,即只有一个实例对象存在.例如在古代,一个国家只能有一个皇帝,在现代则是主席或总统等. 在Java语言中单例模式有以下实现方式 1 ...
- 软件设计模式之单例模式(JAVA)
什么是单例模式? 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系 ...
- 单例模式/ java实现附代码 /
注: 场景和例子出自github的设计模式.传送门:https://github.com/iluwatar/java-design-patterns/tree/master/singleton 意图: ...
- 深入单例模式 - Java实现
单例模式可能是代码最少的模式了,但是少不一定意味着简单,想要用好.用对单例模式,还真得费一番脑筋.本文对Java中常见的单例模式写法做了一个总结,如有错漏之处,恳请读者指正. 饿汉法 顾名思义,饿汉法 ...
- 设计模式之第0章-单例模式(Java实现)
设计模式之第0章-单例模式(Java实现) 当当当当~首先有请最简单的单例模式登场,先来个自我介绍吧 单例模式之自我介绍 我,单例模式(Singleton Pattern)是一个比较简单的模式,我的定 ...
- SingletonPattern(单例模式)-----Java/.Net
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一. 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创建自己的 ...
随机推荐
- linux中sogou输入法崩溃重启
经常在linux中搜狗输入法用着用着就崩溃了,无法输入中文,又不想重启电脑,照着下面在终端输入命令可以重启输入法: 1.先关闭fcitx(小企鹅输入法,提供了良好的中文输入法环境) # killall ...
- <算法图解>读书笔记:第1章 算法简介
阅读书籍:[美]Aditya Bhargava◎著 袁国忠◎译.人民邮电出版社.<算法图解> 第1章 算法简介 1.2 二分查找 一般而言,对于包含n个元素的列表,用二分查找最多需要\(l ...
- 关于DataTable序列化的事儿
今天写了一个小demo,从数据库中读取到了dataTable,想序列化成json字符串,然后传到前端,进行页面展示,其实很简单的一个步骤,谁知道它出错了!!! 出错的原因是:序列化类型为XX的对象时检 ...
- WebStorm重复代码快捷表达
一,问题 平时使用WebStorm时需要很多引用js,重复代码比较多,每次都要写很多次同样的代码,那么如何通过几个快捷键来简单的写出重复代码呢? 问题具体描述: 每次都要写两个script的重复: & ...
- 离校登记网页项目个人总结(Alpha阶段)
个人小结 在Alpha阶段,我和我的小团队六人,经过六天的努力完成了我们最初需求分析里的基本功能,在这里为我们团队的成功表示祝贺.在这个过程中,对于自己的表现觉得既有做的好的方面,也有很多不足需要改进 ...
- sqlserver 评估过期
解决:重新打开安装中心->维护-->版本升级 ,重新输入序列号 即可 sqlserver2008企业级序列号:JD8Y6-HQG69-P9H84-XDTPG-34MBB
- Linux_常用命令简单介绍(netstat,awk,top,tail,head,less,more,cat,nl)
1.netstat netstat -tnl | grep 443 (查看443端口是否被占用) root用户,用netstat -pnl | grep 443 (还可显示出占用本机443端口的进程P ...
- 微信小程序60秒倒计时
微信小程序发送短信验证码后60秒倒计时功能,效果图: 完整代码 index.wxml <!--index.wxml--> <view class="container&qu ...
- ThinkPHP5 打开多语言支持
1.在thinkphp\start.php 页面中添加多语言的切换函数的参数格式,本贴目前只支持两种语言,并注意必须全部小写!全部小写!!全部小写!!!,注意这一步很关键 Lang::setAllow ...
- 牛人的blog,关于推荐,topic model的
http://blog.csdn.net/zhoubl668?viewmode=list