所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该由人来控制,而应该由代码来限制,强制单例。

单例有其独有的使用场景,一般是对于那些业务逻辑上限定不能多例只能单例的情况,例如:类似于计数器之类的存在,一般都需要使用一个实例来进行记录,若多例计数则会不准确。

其实单例就是那些很明显的使用场合,没有之前学习的那些模式所使用的复杂场景,只要你需要使用单例,那你就使用单例,简单易理解。

所以我认为有关单例模式的重点不在于场景,而在于如何使用。

1、常见的单例模式有两种创建方式:所谓懒汉式与饿汉式

(1)懒汉式

何为懒?顾名思义,就是不做事,这里也是同义,懒汉式就是不在系统加载时就创建类的单例,而是在第一次使用实例的时候再创建。

详见下方代码示例:

public classLHanDanli {//定义一个私有类变量来存放单例,私有的目的是指外部无法直接获取这个变量,而要使用提供的公共方法来获取

private static LHanDanli dl = null;//定义私有构造器,表示只在类内部使用,亦指单例的实例只能在单例类内部创建

privateLHanDanli(){}//定义一个公共的公开的方法来返回该类的实例,由于是懒汉式,需要在第一次使用时生成实例,所以为了线程安全,使用synchronized关键字来确保只会生成单例

public static synchronizedLHanDanli getInstance(){if(dl == null){

dl= newLHanDanli();

}returndl;

}

}

(2)饿汉式

又何为饿?饿者,饥不择食;但凡有食,必急食之。此处同义:在加载类的时候就会创建类的单例,并保存在类中。

详见下方代码示例:

public classEHanDanli {//此处定义类变量实例并直接实例化,在类加载的时候就完成了实例化并保存在类中

private static EHanDanli dl = newEHanDanli();//定义无参构造器,用于单例实例

privateEHanDanli(){}//定义公开方法,返回已创建的单例

public staticEHanDanli getInstance(){returndl;

}

}

2、双重加锁机制

何为双重加锁机制?

在懒汉式实现单例模式的代码中,有使用synchronized关键字来同步获取实例,保证单例的唯一性,但是上面的代码在每一次执行时都要进行同步和判断,无疑会拖慢速度,使用双重加锁机制正好可以解决这个问题:

public classSLHanDanli {private static volatile SLHanDanli dl = null;privateSLHanDanli(){}public staticSLHanDanli getInstance(){if(dl == null){synchronized (SLHanDanli.class) {if(dl == null){

dl= newSLHanDanli();

}

}

}returndl;

}

}

看了上面的代码,有没有感觉很无语,双重加锁难道不是需要两个synchronized进行加锁的吗?

......

其实不然,这里的双重指的的双重判断,而加锁单指那个synchronized,为什么要进行双重判断,其实很简单,第一重判断,如果单例已经存在,那么就不再需要进行同步操作,而是直接返回这个实例,如果没有创建,才会进入同步块,同步块的目的与之前相同,目的是为了防止有两个调用同时进行时,导致生成多个实例,有了同步块,每次只能有一个线程调用能访问同步块内容,当第一个抢到锁的调用获取了实例之后,这个实例就会被创建,之后的所有调用都不会进入同步块,直接在第一重判断就返回了单例。至于第二个判断,个人感觉有点查遗补漏的意味在内(期待高人高见)。

不论如何,使用了双重加锁机制后,程序的执行速度有了显著提升,不必每次都同步加锁。

其实我最在意的是volatile的使用,volatile关键字的含义是:被其所修饰的变量的值不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存来实现,从而确保多个线程能正确的处理该变量。该关键字可能会屏蔽掉虚拟机中的一些代码优化,所以其运行效率可能不是很高,所以,一般情况下,并不建议使用双重加锁机制,酌情使用才是正理!

3、类级内部类方式

饿汉式会占用较多的空间,因为其在类加载时就会完成实例化,而懒汉式又存在执行速率慢的情况,双重加锁机制呢?又有执行效率差的毛病,有没有一种完美的方式可以规避这些毛病呢?

貌似有的,就是使用类级内部类结合多线程默认同步锁,同时实现延迟加载和线程安全。

public classClassInnerClassDanli {public static classDanliHolder{private static ClassInnerClassDanli dl = newClassInnerClassDanli();

}privateClassInnerClassDanli(){}public staticClassInnerClassDanli getInstance(){returnDanliHolder.dl;

}

}

如上代码,所谓类级内部类,就是静态内部类,这种内部类与其外部类之间并没有从属关系,加载外部类的时候,并不会同时加载其静态内部类,只有在发生调用的时候才会进行加载,加载的时候就会创建单例实例并返回,有效实现了懒加载(延迟加载),至于同步问题,我们采用和饿汉式同样的静态初始化器的方式,借助JVM来实现线程安全。

其实使用静态初始化器的方式会在类加载时创建类的实例,但是我们将实例的创建显式放置在静态内部类中,它会导致在外部类加载时不进行实例创建,这样就能实现我们的双重目的:延迟加载和线程安全。

4、使用

在Spring中创建的Bean实例默认都是单例模式存在的。

java设计模式转发_Java设计模式之《单例模式》及应用场景(转发:http://www.cnblogs.com/V1haoge/p/6510196.html)...相关推荐

  1. java 设计模式 示例_Java设计模式–示例教程

    java 设计模式 示例 Design Patterns are very popular among software developers. A design pattern is a well- ...

  2. java 外观模式_Java设计模式11:外观模式

    外观模式 外观模式是对象的结构模式,外部与一个子系统的通信必须通过一个统一的外观对象进行.外观模式是一个高层次的接口,使得子系统更易于使用. 医院的例子 现代的软件系统都是比较复杂的.假如把医院比作一 ...

  3. java 影子实例_java设计模式(四)--单例模式

    Singleton最熟悉不过了,下面学习单例模式.转载:http://zz563143188.iteye.com/blog/1847029 单例对象(Singleton)是一种常用的设计模式.在Jav ...

  4. java单例设计模式双重_Java 设计模式 ——单例模式(饿汉,懒汉,双重锁,静态内部类)...

    设计模式: 是在大量的实践中总结和理论化之后优选的代码结构,编程风格,以及解决问题的思考方式.设计模式免去我们自己再思考和摸索.就像是经典的棋谱,不同的棋局,我们用不同的棋谱 俗称"套路&q ...

  5. java 防止反射_Java设计模式(一):单例模式,防止反射和反序列化漏洞

    一.懒汉式单例模式,解决反射和反序列化漏洞 package com.iter.devbox.singleton; import java.io.ObjectStreamException; impor ...

  6. 3种设计模式java小程序_Java设计模式之单例模式(3种实现方式)

    饿汉模式 public class Singleton {//实例化private static Singleton instance=new Singleton();private Singleto ...

  7. java设计模式教程_Java设计模式教程

    java设计模式教程 课程大纲 架构和计算机科学中的设计模式是记录特定专业领域中设计问题的解决方案的正式方法. 这个想法是由建筑师Christopher Alexander在建筑领域引入的,并已被修改 ...

  8. java工厂方法_Java设计模式之工厂方法模式

    2.工厂方法模式 <设计模式之禅>中用神话故事女娲造人来比概述工厂方法模式. 女娲采集黄土捏成人的形状,然后放到八卦炉中烧制,最后放置到大地上生长,工艺过程是没有错的,但是意外随时都会发生 ...

  9. java单例设计模式懒汉_Java设计模式之单例设计模式(懒汉、饿汉)

    [toc] Java设计模式之单例设计模式(懒汉.饿汉) 相信面试过的初中级Java开发的朋友可能都有遇到过单例设计模式的笔试题吧,如果之前没有背下来或者不理解,可以看看下面这篇文章,应该足够应付笔试 ...

最新文章

  1. R语言可视化包ggplot2改变图例(legend)的标题(title)实战
  2. exe一机一码加密工具_Python代码加密混淆
  3. php的filesystem基本函数的学习(1)
  4. 【Java】ArrayList 列表的泛型
  5. 【网络安全】针对 HTTP/2 协议的HTTP Desync攻击
  6. 可塑性极强渐变几何空间,设计中不可或缺的素材
  7. C++ 开发者怒了:这个无用的模块设计最终会害死 C++!
  8. (转载)Http Module 介绍
  9. rhel6 dhcp dns配置小贴士
  10. IT兄弟连 JavaWeb教程 JSP定义
  11. 计算机软件在哪里建文本文档,电脑点击右键的新建文本文档不见了的解决方法 怎么解决电脑点击右键的新建文本文档不见了...
  12. sql的 lpad函数
  13. 计算机网络第四章课后答案(第七版谢希仁著)
  14. 通过修改注册表权限修复ArcMap启动报错问题
  15. POJ 3537 Crosses and Crosses 博弈论 SG函数 记忆化搜索
  16. sodility文档--modifier函数修改器
  17. Mac删除软件之后图标还在怎么办?
  18. 因为一个bug来深入探讨下分页插件PageHelper
  19. 833计算机专业基础是哪本书,想问一下计算机考研统考中,有计算机专业基础综合408和833,有什么区别呢?比如今年西电就是833。哪里可...
  20. 拼多多砍价用户福利贴:通过python模拟操作进行拼多多砍价

热门文章

  1. Hbuilder X 无法预览静态html 显示404
  2. ICnet实时场景分割网络
  3. JVM虚拟机(1)- 内存结构
  4. 微服务架构~BFF和网关是如何演化出来的
  5. JAVA判断两个时间戳,相隔多少分钟
  6. day16正则表达式枚举类
  7. 【艾米莉娅】matrix:valid parentheses括号匹配代码分享(非堆栈版)
  8. python窗体按钮_Python ---(二)Tkinter窗口组件:Button
  9. HanLP-停用词表的使用示例
  10. 头文件和源文件不在同一个目录时头文件路径