首先,单例模式使类在程序生命周期的任何时刻都只有一个实例,

然后,单例的构造函数是私有的,外部程序如果想要访问这个单例类的话,

必须通过 getInstance()来请求(注意是请求)得到这个单例类的实例。

1、饿汉式

  1. package singleton;
  2. /**
  3. * 单例模式保证一个类仅有一个实例,同时这个类还必须提供一个访问该类的全局访问点。
  4. *
  5. * 饿汉式:new之后,便创建对象,以后不再改变,此种方式天生线程安全的
  6. */
  7. public class SingletonDemo1 {
  8.  
  9. //定义一个私有的静态全局变量来保存该类的唯一实例
  10. private static SingletonDemo1 instance=new SingletonDemo1();
  11. //构造函数必须是私有的,这样在外部便无法使用 new 来创建该类的实例
  12. private SingletonDemo1(){
  13. }
  14.  
  15. //定义一个全局访问点 ,设置为静态方法 ,则在类的外部便无需实例化就可以调用该方法
  16. public static SingletonDemo1 getInstance(){
  17. return instance;
  18. }
  19.  
  20. }

2、懒汉式

  1. package singleton;
  2. /**
  3. * 懒汉式:在需要的时候创建对象
     * if()判断,保证线程的安全性
  4. * @author Don
  5. *
  6. */
  7. public class SingletonDemo2 {
  8.  
  9. private static SingletonDemo2 instance;
  10. private SingletonDemo2(){
  11. }
  12.  
  13. //ͬ多线程访问时,当有一个线程访问时就加锁,防止产生多个实例
  14. public static synchronized SingletonDemo2 getInstance(){
  15. if(instance==null){
  16. instance=new SingletonDemo2();
  17. }
  18. return instance;
  19. }
  20. }

3、静态内部类(结合了前两种的优势)

  1. package singleton;
  2. /**
  3. * 静态内部类:兼备了高效调用和延迟加载的优势
  4. * @author Don
  5. *
  6. */
  7. public class SingletonDemo3 {
  8.  
  9. //只有真正调用getInstance(),才会加载静态内部类。加载类时是线程安全的。instance是static final类型
  10. //保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证了线程安全性
  11. private static class SingletonClassInstance{
  12. private static final SingletonDemo3 instance=new SingletonDemo3();
  13. }
  14. private SingletonDemo3(){
  15. }
  16.  
  17. public static SingletonDemo3 getInstance(){
  18. return SingletonClassInstance.instance;
  19. }
  20.  
  21. }

饿汉式和懒汉式区别:

从名字上来说,饿汉和懒汉,

饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,

而懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。

另外从以下两点再区分以下这两种方式:

1、线程安全:

饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,

懒汉式本身是非线程安全的,为了实现线程安全有几种写法,分别是上面的1、2、3,这三种实现在资源加载和性能方面有些区别。

2、资源加载和性能:

  饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成,

而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

至于1、2、3这三种实现又有些区别,

第1种,在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的,

第2种,在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗

第3种,利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以一般我倾向于使用这一种。

什么是线程安全?

  如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。

面试题2:单例模式Singleton的更多相关文章

  1. 【剑指offer】面试题 2. 实现 Singleton 模式

    面试题 2. 实现 Singleton 模式 题目:设计一个类,我们只能生成该类的一个实例. 单例模式:确保一个类只有一个实例,并提供了一个全局访问点. Java 实现 1.饿汉模式 //饿汉模式 p ...

  2. 设计模式之单例模式——Singleton

                        设计模式之单例模式--Singleton 设计意图: 保证类仅有一个实例,并且可以供应用程序全局使用.为了保证这一点,就需要这个类自己创建自己的对象,并且对外有 ...

  3. 【白话设计模式四】单例模式(Singleton)

    转自:https://my.oschina.net/xianggao/blog/616385 0 系列目录 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factor ...

  4. ooad单例模式-Singleton

                                                单例模式Singleton 主要作用是保证在Java应用程序中,一个类Class只有一个实例存在. 比如建立目录 ...

  5. iOS单例模式(Singleton)写法简析

    单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 1.单例模式的要点: 显然单例模式的要点有三个:一是某个类只能有一个实例: ...

  6. 浅谈设计模式--单例模式(Singleton Pattern)

    题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...

  7. 设计模式之——单例模式(Singleton)的常见应用场景

    单例模式(Singleton)也叫单态模式,是设计模式中最为简单的一种模式,甚至有些模式大师都不称其为模式,称其为一种实现技巧,因为设计模式讲究对象之间的关系的抽象,而单例模式只有自己一个对象,也因此 ...

  8. 设计模式之单例模式(Singleton Pattern)

    单例模式 单例模式(Singleton Pattern)在java中算是最常用的设计模式之一,主要用于控制控制类实例的数量,防止外部实例化或者修改.单例模式在某些场景下可以提高系统运行效率.实现中的主 ...

  9. 设计模式(4) -- 单例模式(Singleton)

    设计模式(4)  -- 单例模式(Singleton) 试想一个读取配置文件的需求,创建完读取类后通过New一个类的实例来读取配置文件的内容,在系统运行期间,系统中会存在很多个该类的实例对象,也就是说 ...

  10. IOS单例模式(Singleton)

    IOS单例模式(Singleton)   单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 1.单例模式的要点: 显然单例模 ...

随机推荐

  1. HDU 4734 (数位DP)题解

    思路: dp[pos][pre]代表长度为pos的不大于pre的个数 #include<iostream> #include<cstdio> #include<cstri ...

  2. HDU1540 Tunnel Warfare(线段树区间维护&求最长连续区间)题解

    Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  3. git的软件安装

    1.Git for Winodws 1.*的版本   https://github.com/msysgit/msysgit/releases 2.*的版本   https://github.com/g ...

  4. 处理文字基线 文字对不齐 font-size

    这是我无意中发现的,先记录下 比如你在一个h1标签里面添加文字,或者在其他块级标签添加文字,想让他们间隙少一点,(基线影响)可把行高设置为line-height: 1;就达到消除基线的作用. 建议使用 ...

  5. 【译】第1节--- EF Code First 介绍

    原文:http://www.entityframeworktutorial.net/code-first/entity-framework-code-first.aspx 本教程涵盖了code fir ...

  6. MVC ---- T4(1)

    T4 模板编辑插件:tangibleT4EditorPlusModellingToolsVS2012.msi 下载地址:http://t4-editor.tangible-engineering.co ...

  7. Spring 事物机制总结

    Spring两种事物处理机制,一是声明式事务,二是编程式事务 声明式事物 1)Spring的声明式事务管理在底层是建立在AOP的基础之上的.其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加 ...

  8. 【转】float类型在内存中的表示

    http://www.cnblogs.com/onedime/archive/2012/11/19/2778130.html http://blog.csdn.net/adream307/articl ...

  9. [ios][swift]swift中如果做基本类型的转换

    在swift中如果做基本类型的转换的?比如Int -> Float(Double)Double -> 保留两位小数String -> IntDouble -> String 有 ...

  10. 常用 对象检测 api

    isPrototypeOf()    判断某个 proptotype 对象和某个实例之间的关系 alert(Cat.prototype.isPrototypeOf(cat1)); //true ale ...