原地址:http://blog.csdn.net/xu__cg/article/details/70182988

Java单例模式是一种常见且较为简单的设计模式。单例模式,顾名思义一个类仅能有一个实例,并且向整个系统提供这一个实例。 
单例模式的特点:

  • 单例类仅能有一个实例。
  • 单例类必须为自己创建实例。
  • 单例类必须向外界提供获取实例的方法。 
    以下是几种实现方法

一、懒汉式单例(能够延时加载)

  1. public class SingleTon {
  2. private static SingleTon instance = null ;
  3. private SingleTon(){
  4. }
  5. public static SingleTon getInstance(){
  6. if(instance==null){
  7. instance=new SingleTon();
  8. }
  9. return instance ;
  10. }
  11. }

通过是构造方法私有化使该类不能在外界实例化,只能通过public方法获取实例,从而保证实例唯一。 
但是以上的代码是线程不安全的,多线程并发的情况下,SingleTon可能产生多个实例,可以通过以下方法对getInstance方法进行改进从而保证懒汉式单例线程安全。

1.在getInstance()方法上加上同步

  1. public class SingleTon {
  2. private static SingleTon instance = null ;
  3. private SingleTon(){
  4. }
  5. //方法同步,调用效率低!
  6. public static synchronized SingleTon getInstance(){
  7. if(instance==null){
  8. instance=new SingleTon();
  9. }
  10. return instance ;
  11. }
  12. }

2.静态内部类式

  1. public class SingleTon {
  2. private static class SingletonClassInstance {
  3. private static final SingleTon instance=new SingleTon();
  4. }
  5. private SingleTon(){
  6. }
  7. //方法没有同步,调用效率高!
  8. public static SingleTon getInstance(){
  9. return SingletonClassInstance.instance ;
  10. }
  11. }

3.双重校验锁式

  1. public class SingleTon {
  2. private volatile static SingleTon instance ;
  3. private SingleTon(){
  4. }
  5. public static SingleTon getInstance(){
  6. if(instance==null){
  7. synchronized(SingleTon.class ){
  8. if(instance==null){
  9. instance=new SingleTon();
  10. }
  11. }
  12. }
  13. return instance ;
  14. }
  15. }

二、饿汉式单例 (不能够延时加载)

  1. public class SingleTon {
  2. //类初始化时,立即加载这个对象,加载类时,天然的是线程安全的!
  3. private static SingleTon instance=new SingleTon();
  4. private SingleTon(){
  5. }
  6. //方法没有同步,调用效率高!
  7. public static SingleTon getInstance(){
  8. return instance ;
  9. }
  10. }

饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

三、枚举式单例

  1. public enum SingleTon {
  2. //这个枚举元素,本身就是单例对象!
  3. INSTANCE;
  4. //添加自己需要的操作!
  5. public void singletonOperation(){
  6. }
  7. }

枚举式单例是线程安全的,调用效率高,并且可以天然的防止反射和反序列化漏洞。

四、防止反射和反序列化


事实上,通过Java反射或反序列化能够获取构造方法为private的类实例,那么所有的单例都会失效。所以为了避免这种后果,需要采取相应措施。

  1. /**
  2. *懒汉式单例模式(如何防止反射和反序列化漏洞)
  3. *
  4. */
  5. public class SingleTon implements Serializable {
  6. //类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)。
  7. private static SingleTon instance ;
  8. private SingleTon(){ //私有化构造器
  9. if(instance!=null){
  10. throw new RuntimeException(); //防止反射
  11. }
  12. }
  13. //方法同步,调用效率低!
  14. public static synchronized SingleTon getInstance(){
  15. if(instance==null){
  16. instance=new SingleTon();
  17. }
  18. return instance ;
  19. }
  20. //反序列化时,如果定义了readResolve()则直接返回此方法指定的对象。而不需要单独再创建新对象!
  21. private Object readResolve() throws ObjectStreamException {
  22. return instance ;
  23. } }

五、如何选用单例模式实现方式

  • 单例对象占用资源少,且不需要延时加载:枚举式 好于 饿汉式
  • 单例对象占用资源大,且需要延时加载:静态内部类式 好于 一般懒汉式

Java设计模式学习01——单例模式(转)的更多相关文章

  1. Java设计模式学习记录-单例模式

    前言 已经介绍和学习了两个创建型模式了,今天来学习一下另一个非常常见的创建型模式,单例模式. 单例模式也被称为单件模式(或单体模式),主要作用是控制某个类型的实例数量是一个,而且只有一个. 单例模式 ...

  2. Java设计模式学习资源汇总

    本文记录了Java设计模式学习书籍.教程资源.此分享会持续更新: 1. 设计模式书籍 在豆瓣上搜索了一把,发现设计模式贯穿了人类生活的方方面面.还是回到Java与程序设计来吧. 打算先归类,再浏览,从 ...

  3. Java设计模式之《单例模式》及应用场景

    摘要: 原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6510196.html 所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该 ...

  4. Java设计模式学习记录-模板方法模式

    前言 模板方法模式,定义一个操作中算法的骨架,而将一些步骤延迟到子类中.使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤. 模板方法模式 概念介绍 模板方法模式,其实是很好理解的,具体 ...

  5. Java设计模式学习记录-状态模式

    前言 状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题.状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活多变.这样在客户端使 ...

  6. Java设计模式学习记录-观察者模式

    前言 观察者模式也是对象行为模式的一种,又叫做发表-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模式. 咱们目前用的最多的就是各种MQ(Message Queue ...

  7. Java设计模式学习记录-备忘录模式

    前言 这次要介绍的是备忘录模式,也是行为模式的一种 .现在人们的智能手机上都会有备忘录这样一个功能,大家也都会用,就是为了记住某件事情,防止以后自己忘记了.那么备忘录模式又是什么样子的呢?是不是和手机 ...

  8. Java设计模式学习记录-迭代器模式

    前言 这次要介绍的是迭代器模式,也是一种行为模式.我现在觉得写博客有点应付了,前阵子一天一篇,感觉这样其实有点没理解透彻就写下来了,而且写完后自己也没有多看几遍,上次在面试的时候被问到java中的I/ ...

  9. Java设计模式学习记录-解释器模式

    前言 这次介绍另一个行为模式,解释器模式,都说解释器模式用的少,其实只是我们在日常的开发中用的少,但是一些开源框架中还是能见到它的影子,例如:spring的spEL表达式在解析时就用到了解释器模式,以 ...

随机推荐

  1. 在eclipse中使用git clone 别人共享在Github的代码和上传到自己的仓库!

    原文地址:http://www.itdaan.com/blog/2014/10/24/ff5e03b5cefef19e1b6fbb7b49809846.html1.在eclipse中安装git:打开e ...

  2. .NET 中的轻量级线程安全

    对线程安全有要求的代码中,通常会使用锁(lock).自 .NET 诞生以来就有锁,然而从 .NET Framework 4.0 开始,又诞生了 6 个轻量级的线程安全方案:SpinLock, Spin ...

  3. iOS客户端打包自动集成weex方案

    我司在2017年已经部分使用weex开发,然而开发weex 的人都知道,在前端开发完成之后需要集成到 安卓和iOS 各个app 之中.每次修改都要重新copy给各个app 负责人去打包,因此这是一种重 ...

  4. Linux驱动开发基础知识

    常用命令 lsmod: list module,将模块列表显示),功能是打印出当前内核中已经安装的模块列表 insmod: install module,安装模块,功能是向当前内核中去安装一个模块,用 ...

  5. python---time 相关, str 转timestamp

    df['col'] = pd.to_datetime(df['col']) from datetime import date from datetime import datetime d = da ...

  6. UML基本架构建模--类的术语和概念

     Terms and Concepts 术语和概念   A classis a description of a set of objects that share the same attrib ...

  7. bean作用域

    https://blog.csdn.net/u011468990/article/details/49995865 其中比较常用的是singleton和prototype两种作用域.对于singlet ...

  8. Jetty小计,比之tomcat调试还是不方便

    不需要额外的工程支持,不需要硬盘中有tomcat之类的额外文件 Jetty的Debug:右键Debug as... Maven Builder Jetty相关的配置文件如下: <profiles ...

  9. Linux命令 改变文档权限及所有者

    Linux命令 改变文档权限及所有者 chgrp :改变档案所属群组 chown :改变档案拥有者 chmod :改变档案的权限, SUID, SGID, SBIT等等的特性 chgrp说明及范例 [ ...

  10. MySql触发器实现数据同步学习

    触发器实现:(增.删.改操作事件触发数据单向同步)数据库触发器教程:https://www.cnblogs.com/phpper/p/7587031.html同步代码: DELIMITER $ DRO ...