很多求职者在面试过程中都被问到了单例模式,最常见的问题,比如,每种单例模式的区别是什么?哪些模式是线程安全的?你们项目里用的哪种单例模式?原来没有注意这个问题,回来赶紧打开项目查看了一下代码,才发现我们的项目用到了枚举。有的面试官还会让你手写一种单例模式,我建议大家就写自己项目中用到的那种。下面我就说一说我学到的单例模式。

一、单例模式的好处

减少系统资源的消耗。因为这种工具类基本上贯穿程序始终,必然会频繁调用.如果每一次调用都要重新生成实例,那么在内存堆中就会分配相应的内存空间,所以使用单例模式会提高程序的运行速度,减少资源消耗。

二、单例模式的特点

1、单例类只能有一个实例:确保某个类只有一个实例

2、单例类必须自己创建自己的唯一实例:在需要创建单例模式的这个类里,自己new了一个自己的对象

3、单例类必须给所有其他对象提供这一实例:因为单例类的构造是privite的,所以要给外部提供一个方法来访问这个实例

三、常见单例模式的使用方法和优缺点

1、饿汉模式,可用。在初始化的时候就完成实例化了,避免了线程同步的问题,缺点就是无论这个类是否被使用,都会创建一个instance对象,不能延迟加载。如果从始至终都没有用过,造成内存浪费。在类加载的时候就完成了实例化,没有实现延迟加载。

  1. public class Singleton {
    //实例化对象
  2. private static Singleton instance = new Singleton();
    //私有构造
  3. private Singleton (){}
    //对外提供一个公共的方法访问这个实例
  4. public static Singleton getInstance() {
  5. return instance;
  6. }
  7. }

2、饿汉变种,线程安全,可用。将类实例化的过程放在了静态代码块中,也是在类加载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点和上面是一样的。

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

3、懒汉模式,线程不安全,不推荐用。多线程的时候不能保证实例是唯一的了。比如线程a要使用Singleton,第一次调用发现instance为null,开始创建实例还没完成创建,就在这个时候,CPU去执行线程b了,b发现instance也为null,还会去创建实例。b创建完之后,回来执行a。线程a不会再回去检查instance是否为null了,这样线程a和b各自拥有一个实例,单例失败。但是可以实现延迟加载。

  1. public class Singleton {
    //没有final
  2. private static Singleton instance;
    //私有构造
  3. private Singleton (){}
    //对外提供一个公共方法来访问这个实例
  4. public static Singleton getInstance() {
  5. if (instance == null) {
  6. instance = new Singleton();
  7. }
  8. return instance;
  9. }
  10. }

4、懒汉模式,线程安全。解决饿汉模式带来的问题,就是在创建实例的时候添加一把锁,一个线程必须等待另外一个线程创建完成后才能调用这个方法,这就保证了单例的唯一性了。但是synchronized修饰的同步块要比一般的代码段慢上几倍的,如果多次调用getInstance()这个方法,会影响性能,可以实现延迟加载。

  1. public class Singleton {
    //没有final,因为下边要对instance重新赋值
  2. private static Singleton instance;
    //私有构造
  3. private Singleton (){}
  4. public static synchronized Singleton getInstance() {
  5. if (instance == null) {
  6. instance = new Singleton();
  7. }
  8. return instance;
  9. }
  10. }

5、静态内部类,线程安全,推荐用。实现了延迟加载,减少内部开销,内部类SingletonHolder 只有在getInstance()方法第一次调用的时候才会被加载,内部类加载的时候实现了加载一下INSTANCE 。

  1. public class Singleton {
    //内部类实例化INSTANCE 
  2. private static class SingletonHolder {
  3. private static final Singleton INSTANCE = new Singleton();
  4. }
  5. private Singleton (){}
    //对外提供一个公共方法访问INSTANCE 
  6. public static final Singleton getInstance() {
  7. return SingletonHolder.INSTANCE;
  8. }
  9. }

6、双重校验,线程安全,推荐用。既实现线程安全,又能够使性能不受到很大的影响,因为只有在第一次创建实例的时候才会走同步块。

  1. public class Singleton {
    //双重校验关键字volatile,被volatile修饰的值,将不会被本地线程缓存,保证所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确处理该变量,但是使用volatile运行效率并不高。不建议大量使用双重校验。
  2. private volatile static Singleton singleton;
  3. private Singleton (){}
  4. public static Singleton getSingleton() {
    //第一次校验,是否实例化了
  5. if (singleton == null) {
    //第二次校验,同步块,线程安全的创建实例
  6. synchronized (Singleton.class) {
  7. if (singleton == null) {
  8. singleton = new Singleton();
  9. }
  10. }
  11. }
  12. return singleton;
  13. }
  14. }    

四、单例模式适用的场合

1、需要频繁的进行创建和销毁的对象

2、创建对象时耗时过多或耗费资源过多,但又经常用到的对象

3、工具类对象

4、频繁访问数据库或文件的对象

  

  

  

java中常见的单例模式详解的更多相关文章

  1. java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET

    java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET 亲,“社区之星”已经一周岁了!      社区福利快来领取免费参加MDCC大会机会哦    Tag功能介绍—我们 ...

  2. Java中的main()方法详解

    在Java中,main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这个方法和其他的方法有很大的不同,比如方法的名字必须是main,方法必须是 ...

  3. PHP开发中常见的安全问题详解和解决方法(如Sql注入、CSRF、Xss、CC等

    页面导航: 首页 → 网络编程 → PHP编程 → php技巧 → 正文内容 PHP安全 PHP开发中常见的安全问题详解和解决方法(如Sql注入.CSRF.Xss.CC等) 作者: 字体:[增加 减小 ...

  4. Java I/O : Java中的进制详解

    作者:李强强 上一篇,泥瓦匠基础地讲了下Java I/O : Bit Operation 位运算.这一讲,泥瓦匠带你走进Java中的进制详解. 一.引子 在Java世界里,99%的工作都是处理这高层. ...

  5. JAVA中的GC机制详解

    优秀Java程序员必须了解的GC工作原理 一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的交互,因为有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只 ...

  6. Java中的枚举使用详解

    转载至:http://www.cnblogs.com/linjiqin/archive/2011/02/11/1951632.html package com.ljq.test; /** * 枚举用法 ...

  7. java中list和map详解

    一.概叙 List , Set, Map都是接口,前两个继承至Collection接口,Map为独立接口, List下有ArrayList,Vector,LinkedList Set下有HashSet ...

  8. Java中getBytes()方法--使用详解

    getBytes()方法详解 在Java中,String的getBytes()方法是得到一个操作系统默认的编码格式的字节数组.这表示在不同的操作系统下,返回的东西不一样! 1. str.getByte ...

  9. Java中JNI的使用详解第二篇:JNIEnv类型和jobject类型的解释

    上一篇说的是一个简单的应用,说明JNI是怎么工作的,这一篇主要来说一下,那个本地方法sayHello的参数的说明,以及其中方法的使用 首先来看一下C++中的sayHello方法的实现: JNIEXPO ...

随机推荐

  1. java使用验证码进行登录验证

    随机生成4位验证码,将生成的4位数字字母数字放入session private static void outputVerifyCode(HttpServletRequest request, Htt ...

  2. 用1个 2个3个 5个div实现 十字架

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. NET Core开发-使用Nancy框架

    NET Core开发-使用Nancy框架 Nancy简介 Nancy是一个轻量级的独立的框架,下面是官网的一些介绍: Nancy 是一个轻量级用于构建基于 HTTP 的 Web 服务,基于 .NET ...

  4. 在美国,一名 Uber 司机能赚多少?

    在美国,Uber 司机是最热门的职业.有了 uberX,任何有车一族都能成为司机.Uber 让我们很容易成为司机. 虽然 Uber 做不到赚得盆满钵满,但对于水深火热的司机这一行来说,多了许多盈利机会 ...

  5. python 入门快速学习整理

    Python 入门学习 1  : 对象类型 1 1.1 列表 1 1.2 字典 2 1.3 元组 2 1.4 元组 2 1.4 文件 3 2  : 条件和循环语句 3 2.1  if else语句 3 ...

  6. Ordering Tasks(拓扑排序+dfs)

    Ordering Tasks John has n tasks to do. Unfortunately, the tasks are not independent and the executio ...

  7. 最新 Cocos2d-x 3.2 开发环境搭建(windows环境下)

    本篇是基于Cocos2d-x-3.2和vs2012的环境下配置. 1.先从官方站点(www.cocos2d-x.org)下载 Cocos2d-x-3.2文件. 2.因为Cocos2d-x 3.0以上的 ...

  8. VIM在文件夹中查找

    在vim中提供2中方法来在其他文件或者文件夹中搜索字符串,第一种是vimgrep还有一种是grep. 如果只是在当前打开的文件中查找字符串的,使用 :? 后面加上想要搜索的字符串就可以. 这里要解决的 ...

  9. SMACSS:一个关于CSS的最佳实践-1.Overview

    什么是SMACSS? SMACSS(发音"smacks"),全称Scalable and Modular Architecture for CSS.顾名思义,SMACSS是一个可扩 ...

  10. Echarts数据图表插件--开源、大气、强大

    个人觉得不错,分享给大家. 教程地址:http://echarts.baidu.com/, 开源项目:https://github.com/ecomfe/echarts