设计模式(一)单例模式的七种写法

1. 饿汉模式

public class Singleton {  private static Singleton instance = new Singleton();  private Singleton (){}public static Singleton getInstance() {  return instance;  }  }
View Code

这种方式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。 这种方式基于类加载机制避免了多线程的同步问题,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到懒加载的效果。

2. 懒汉模式(线程不安全)

public class Singleton {  private static Singleton instance;  private Singleton (){}   public static Singleton getInstance() {  if (instance == null) {  instance = new Singleton();  }  return instance;  }  }
View Code

懒汉模式申明了一个静态对象,在用户第一次调用时初始化,虽然节约了资源,但第一次加载时需要实例化,反映稍慢一些,而且在多线程不能正常工作。

3. 懒汉模式(线程安全)

public class Singleton {  private static Singleton instance;  private Singleton (){}public static synchronized Singleton getInstance() {  if (instance == null) {  instance = new Singleton();  }  return instance;  }  }
View Code

这种写法能够在多线程中很好的工作,但是每次调用getInstance方法时都需要进行同步,造成不必要的同步开销,而且大部分时候我们是用不到同步的,所以不建议用这种模式。

4. 双重检查模式 (DCL)

public class Singleton {  private volatile static Singleton singleton;  private Singleton (){}   public static Singleton getInstance() {  if (instance== null) {  synchronized (Singleton.class) {  if (instance== null) {  instance= new Singleton();  }  }  }  return singleton;  }  }
View Code

这种写法在getSingleton方法中对singleton进行了两次判空,第一次是为了不必要的同步,第二次是在singleton等于null的情况下才创建实例。在这里用到了volatile关键字,不了解volatile关键字的可以查看Java多线程(三)volatile域这篇文章,在这篇文章我也提到了双重检查模式是正确使用volatile关键字的场景之一。
在这里使用volatile会或多或少的影响性能,但考虑到程序的正确性,牺牲这点性能还是值得的。 DCL优点是资源利用率高,第一次执行getInstance时单例对象才被实例化,效率高。缺点是第一次加载时反应稍慢一些,在高并发环境下也有一定的缺陷,虽然发生的概率很小。DCL虽然在一定程度解决了资源的消耗和多余的同步,线程安全等问题,但是他还是在某些情况会出现失效的问题,也就是DCL失效,在《java并发编程实践》一书建议用静态内部类单例模式来替代DCL。

5. 静态内部类单例模式

public class Singleton { private Singleton(){}public static Singleton getInstance(){  return SingletonHolder.sInstance;  }  private static class SingletonHolder {  private static final Singleton sInstance = new Singleton();  }  
}
View Code

第一次加载Singleton类时并不会初始化sInstance,只有第一次调用getInstance方法时虚拟机加载SingletonHolder 并初始化sInstance ,这样不仅能确保线程安全也能保证Singleton类的唯一性,所以推荐使用静态内部类单例模式。

6. 枚举单例

public enum Singleton {  INSTANCE;  public void doSomeThing() {  }  }
View Code

默认枚举实例的创建是线程安全的,并且在任何情况下都是单例,上述讲的几种单例模式实现中,有一种情况下他们会重新创建对象,那就是反序列化,将一个单例实例对象写到磁盘再读回来,从而获得了一个实例。反序列化操作提供了readResolve方法,这个方法可以让开发人员控制对象的反序列化。在上述的几个方法示例中如果要杜绝单例对象被反序列化是重新生成对象,就必须加入如下方法:

private Object readResolve() throws ObjectStreamException{
return singleton;
}
View Code

枚举单例的优点就是简单,但是大部分应用开发很少用枚举,可读性并不是很高,不建议用。

7. 使用容器实现单例模式

public class SingletonManager { private static Map<String, Object> objMap = new HashMap<String,Object>();private Singleton() { }public static void registerService(String key, Objectinstance) {if (!objMap.containsKey(key) ) {objMap.put(key, instance) ;}}public static ObjectgetService(String key) {return objMap.get(key) ;}
}
View Code

用SingletonManager 将多种的单例类统一管理,在使用时根据key获取对象对应类型的对象。这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。

总结

到这里七中写法都介绍完了,至于选择用哪种形式的单例模式,取决于你的项目本身,是否是有复杂的并发环境,还是需要控制单例对象的资源消耗。

 

8.注意事项

1.使用反射能够破坏单例模式,所以应该慎用反射

1 Constructor con = Singleton.class.getDeclaredConstructor();
2 con.setAccessible(true);
3 // 通过反射获取实例
4 Singleton singeton1 = (Singleton) con.newInstance();
5 Singleton singeton2 = (Singleton) con.newInstance();
6 System.out.println(singeton1==singeton2);//结果为false,singeton1和singeton2将是两个不同的实例
  • 可以通过当第二次调用构造函数时抛出异常来防止反射破坏单例,以懒汉式为例:
     1 public class Singleton {
     2     private static boolean flag = true;
     3     private static Singleton single = null;
     4 
     5     private Singleton() {
     6         if (flag) {
     7             flag = !flag;
     8         } else {
     9             throw new RuntimeException("单例模式被破坏!");
    10         }
    11     }
    12 
    13     public static Singleton getInstance() {
    14         if (single == null) {
    15             single = new Singleton();
    16         }
    17         return single;
    18     }
    19 }

2.反序列化时也会破坏单例模式,可以通过重写readResolve方法避免,以饿汉式为例

 1 public class Singleton implements Serializable {
 2     private Singleton() {
 3     }
 4 
 5     private static final Singleton single = new Singleton();
 6 
 7     public static Singleton getInstance() {
 8         return single;
 9     }
10 
11     private Object readResolve() throws ObjectStreamException {//重写readResolve()
12         return single;//直接返回单例对象
13     }
14 }

 

转载于:https://www.cnblogs.com/ganchuanpu/p/6618995.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/541694.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能关机软件 c语言,智能关机软件

智能关机软件是一款免费共享关机软件。智能关机软件不但具有定时关机、自动关机的功能&#xff0c;而且还可以进行定时提醒信息、打开文件、打开网页、重启计算机、注销用户、锁定计算机、计算机休眠、计算机待机、关闭显示器&#xff0c;并且可以进行多任务计划&#xff0c;可…

iOS开发之解决系统数字键盘无文字时delete键无法监听的技巧

最近在做用户登录获取验证码时添加图形验证码功能&#xff0c;就是只有正确输入图形验证码才能收到后台发送的短信验证码。效果如下&#xff1a; 看起来虽然是个小功能&#xff0c;但是实际操作起来&#xff0c;会发现苹果给我们留下的坑&#xff0c;当然更多的是自己给自己挖的…

连接fiddler后手机无法显示无网络

升级了fiddler到4.6版本&#xff0c;手机设置代理后提示无网络&#xff0c;试试以下解决方法&#xff1a; 1.fiddler升级后对应的.net framework也要升级&#xff0c;安装最新的.net framework 4.6&#xff0c;升级安装后&#xff0c;可以正确抓包啦 2.如果上述方法无效&#x…

android 图片叠加xml,Android实现图片叠加效果的两种方法

本文实例讲述了Android实现图片叠加效果的两种方法。&#xff0c;具体如下&#xff1a;效果图&#xff1a;第一种&#xff1a;第二种&#xff1a;第一种是通过canvas画出来的效果:public void first(View v) {// 防止出现Immutable bitmap passed to Canvas constructor错误Bit…

Win10系列:VC++ 定时器

计时器机制俗称"心跳"&#xff0c;表示以特定的频率持续触发特定事件和执行特定程序的机制。在开发Windows应用商店应用的过程中&#xff0c;可以使用定义在Windows::UI::Xaml命名空间中的DispatcherTimer类来创建计时器。DispatcherTimer类包含了如下的成员&#xf…

dbms系统 rdbms_DBMS与传统文件系统之间的区别

dbms系统 rdbmsIntroduction 介绍 DBMS and Traditional file system have some advantages, disadvantages, applications, functions, features, components and uses. So, in this article, we will discuss these differences, advantages, disadvantages and many other …

android 百度地图api密钥,Android百度地图开发获取秘钥之SHA1

最近在做一个关于百度地图的开发。不过在正式开发之前还必须要在百度地图API官网里先申请秘钥&#xff0c;而在申请秘钥的过程中&#xff0c;就需要获取一个所谓的SHA1值。如上所示&#xff0c;但是由于不是正式开发&#xff0c;所以以上的发布版和开发版的SHA1可以先填写相同。…

华为荣耀七能升级鸿蒙系统吗,华为鸿蒙系统来了,你知道哪些华为手机荣耀手机可以升级吗?...

从鸿蒙系统第一次开始登场&#xff0c;到现在慢慢有许多鸿蒙系统设备出现&#xff0c;手机市场的格局似乎又要升级变化了。科技树儿了解到&#xff0c;在某数码博主经过和相关人员的沟通核实之后&#xff0c;目前暂定的是搭载华为麒麟710芯片以上的机型&#xff0c;无论华为或荣…

Tcl与Design Compiler (十二)——综合后处理

本文如果有错&#xff0c;欢迎留言更正&#xff1b;此外&#xff0c;转载请标明出处 http://www.cnblogs.com/IClearner/ &#xff0c;作者&#xff1a;IC_learner 概述 前面也讲了一些综合后的需要进行的一些工作&#xff0c;这里就集中讲一下DC完成综合了&#xff0c;产生了…

四则运算网页版

一.设计思想&#xff1a; 1&#xff09;写出一个菜单界面&#xff0c;有两个选项一个是分数&#xff0c;一个是整数。 2&#xff09;而这两个标签后面则是转向其更详细的菜单&#xff0c;题目数量&#xff0c;有无括号&#xff0c;运算的项数等等详细功能&#xff0c;再点击这两…

分布式交换机配置备份和还原

1.备份和还原vSphere Distributed Switch配置 1.1导出 vSphere Distributed Switch 配置 可以将 vSphere Distributed Switch 和分布式端口组配置导出到某一文件。该文件保留有效的网络配置&#xff0c;使这些配置能够传输至其他环境。 步骤&#xff1a; 1) 在 vSphere Web Cli…

华为鸿蒙系统好在哪,华为鸿蒙2.0可以替代安卓吗,华为鸿蒙2.0优势在哪

在华为开发者大会上&#xff0c;华为消费业务CEO 余承东&#xff0c;正式发布鸿蒙OS2.0&#xff0c;并宣布华为鸿蒙OS将全面启用全场景生态&#xff0c;并将于2020年12月发布手机版。余承东还表示&#xff0c;明年&#xff0c;华为的智能手机将全面升级&#xff0c;以支持鸿蒙操…

html5画分形图形,2.5 绘制透明图形 - HTML5 Canvas 实战

对于需要图形分层的应用&#xff0c;经常需要处理透明度。本节&#xff0c;我们将学习如何使用全局透明度设置图形的透明度。图2-5 绘制透明图形绘制步骤按照以下步骤&#xff0c;在一个不透明的矩形之上&#xff0c;绘制一个透明的圆&#xff1a;1. 定义2D画布上下文&#xff…

html5录音功能代码,recorder.js 基于 HTML5 实现录音功能

recorder.js 基于 HTML5 实现录音功能2020-06-23 01:49:56recorder.jsmicrophone基于HTML5的录音功能&#xff0c;输出格式为mp3文件。前言完全依赖H5原生API所涉及的API&#xff1a;WebRTC、AudioContext、Worker、Video/Audio API、Blob、URL兼容性Chrome、FF、Edge、QQ、360…

html5页面引入jquery,如何在javascript中引入jQuery?

jquery是一个用来代替JavaScript来快捷书写前端脚本语言的库&#xff0c;jquery可以大大的简化复杂的js代码&#xff0c;使开发人员专注于实现页面的效果。jquery的导入方式有两种&#xff0c;一种是本地导入&#xff0c;一种是从超链接导入。方式一&#xff1a;本地导入我们可…

湖南省普通招生2021高考成绩查询,湖南省2021八省联考成绩可查,附查询入口及往年分数线...

原标题&#xff1a;湖南省2021八省联考成绩可查&#xff0c;附查询入口及往年分数线湖南省2021年八省联考新高考适应性考试成绩公布&#xff0c;这次大家考的如何呢&#xff1f;此次成绩排名对于考生择校及志愿填报有一定的参考意义&#xff0c;小盒一时间收集整理相关消息&…

Ubuntu抛弃了Untiy转向Gnome,美化之路怎么办?不用怕咱一步一步大变身!

跨平台系列汇总&#xff1a;http://www.cnblogs.com/dunitian/p/4822808.html#linux 常用软件安装系统软件卸载&#xff1a;http://www.cnblogs.com/dunitian/p/6670560.html 1.下载UnityGnome版本 https://wiki.ubuntu.com/UbuntuGNOME/GetUbuntuGNOME 2.打开终端 or CtrlAltT…

html木桶布局,CSS3如何实现图片木桶布局?(附代码)

本篇文章给大家通过代码示例介绍一下使用CSS3实现图片木桶布局的方法。有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对大家有所帮助。高度相同&#xff0c;而宽度不一样的布局&#xff0c;称之为木桶布局。它有几个鲜明的特点&#xff1a; 每行的图片…

万用表怎么测量电池容量_万用表检测光电耦合器的常用技巧

光电耦合器又称光耦合器或光耦&#xff0c;它属于较新型的电子产品&#xff0c;已经广泛应用在彩色电视机、彩色显示器、计算机、音视频等各种控制电路中。光电耦合器的构成和原理常见的光电耦合器有 4 脚直插和 6 脚两种&#xff0c;它们的典型实物外形和电路符号如图 3-4所示…

hanlp 训练模型_LTP 4.0!单模型完成6项自然语言处理任务

来源|哈工大SCIR语言技术平台&#xff08;Language Technology Platform, LTP&#xff09;是哈工大社会计算与信息检索研究中心&#xff08;HIT-SCIR&#xff09;历时多年研发的一整套高效、高精度的中文自然语言处理开源基础技术平台。该平台集词法分析&#xff08;分词、词性…