概念

引用维基百科对单例的说明:

单例模式,也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在

继续引用维基百科的实现思路:

实现单例模式的思路是:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。

单例的思路就这么简单,不像其他的设计模式那样一般有几个类。它只有一个类。

Java 中的单例实现

懒汉式与饿汉式

在讨论 Java 的单例模式时,猿们一般会提到两者实现方式:懒汉式饿汉式 。为什么会有这两种叫法?看了实现代码后,相信您会忽然大悟。

饿汉式,我是饿汉,不能等,创建(类)时就要给我吃的(实例化对象),不然我会饿死:

public class Singleton{//创建类时就实例化出单例。private final static Singleton INSTANCE = new Singleton();//使用私有的构造器来阻止外部(其他代码)实例化该对象private Singleton(){}//由于该类的构造方法是私有的,只能在该类内部实例化对象。因此必须提供一个静态的公有方法作为出口,提供单例。public static Singleton getInstance(){return INSTANCE;}
}

懒汉式, 我是懒汉,你叫我干活(给 INSTANCE new 一个单例)才干,懒是我的天性,这不能怪我:

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

OK,单例模式就是这么简单,结束了。呵呵,真的结束了吗?图样图森破!

上面的两个实现确实是实现了汉式和懒汉式。而且它们在单线程下能很好地运行。但如果我们把它们应用在多线程下呢?试一下就知道,饿汉式依然坚挺,潇洒应对。但懒汉式就瞬间爆炸了!没办法谁叫你懒,出来混总是要还的。即使是代码,懒也要付出代价~~开玩笑的^_^,爆炸的原因肯定不是懒的原因啦,是线程同步的问题,造成了非线程安全的懒汉式。

既然上面的懒汉式在多线程下爆炸了,我们就要去拯救它,总不能见死不救吧~~

多线程下懒汉式的自我拯救

知道懒汉式爆炸的原因时线程同步的问题,我们最简单的拯救方法就是直接进行同步加锁,创建线程安全的懒汉式

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

通过简单的对 getInstance 方法进行加锁就可以把非线程安全的懒汉式改为线程安全的,简单吧!但,正如天下没免费的午餐一样,如此简单的拯救方法肯定是要付出代价的。因此这种实现方法会降低效率。

好吧,效率低下,我改还不行。经过改改改后,我们又得出了另外一种线程安全懒汉式单例:双重校验锁(Double-Checked Locking)

public class Singleton{private static volatile Singleton INSTANCE;private Singleton(){}public static Singleton getInstance(){if(INSTANCE == null){synchronized(Singleton.class){if(INSTANCE == null){INSTANCE = new Singleton();}}}return INSTANCE;}
}

该方法比之前的线程安全懒汉式效率高的原因是,之前的实现方法每次获取单例是都要进行同步,每一次只能有一个线程进入 getInstance 方法获取实例;而该方法把同步块缩小了,而且只在 INSTANCE 为 null 时才会进行同步访问(也就是说只需要一次同步)。之后都不需要同步,可以并发地获取实例。

很多人都知道,JDK 1.5 之前利用这种方法实现是有问题的。但在 JDK 1.5 后,Java 的内存已经修改了,该方法在 1.5 后能正常运行,可以放心使用。

其他的实现方法

使用静态内部类实现

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

该方法利用了静态内部类的特性实现了类似与懒汉式的单例模式

(单元素的)枚举实现

public enum Singleton{INSTANCE;
}

枚举实现的单例已经简单到不能再简单了,可以直接使用 Singleton.INSTANCE 来获取单例。它虽然简单,但也是线程安全的实现方法,并且也是可序列化的。在 Effective Java 第二版里也推荐使用这种方法: 单元素的枚举类型已经成为实现 Singleton 的最佳方法

单例在 Java 中的应用

  • Java.awt.Toolkit with getDefaultToolkit()
  • Java.awt.Desktop with getDesktop()
  • java.lang.Runtime

java.lang.Runtime 使用的单例(饿汉式,不涉及到线程安全):

public class Runtime{private static Runtime currentRuntime = new Runtime();public static Runtime getRuntime(){return currentRuntime;}private Runtime(){}//... 其他方法
}

参考

维基百科
StackExchange
使用枚举实现单例
Effective Java 第三条建议

转载于:https://www.cnblogs.com/averey/p/4499358.html

单例模式(Singleton)小记相关推荐

  1. python3中的单例模式Singleton

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2019-01-21 09:09:09 # @Author : cdl (1217096 ...

  2. Android设计模式——单例模式(Singleton)

    二十三种设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元 ...

  3. 【设计模式】单例模式 Singleton Pattern

    通常我们在写程序的时候会碰到一个类只允许在整个系统中只存在一个实例(Instance)  的情况, 比如说我们想做一计数器,统计某些接口调用的次数,通常我们的数据库连接也是只期望有一个实例.Windo ...

  4. python单例_Python - 单例模式(Singleton)

    单例模式(Singleton) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/23374575 单例模式 , 类的实例从始至终, ...

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

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

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

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

  7. 设计模式(21):创建型-单例模式(Singleton)

    设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...

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

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式包括:1.FactoryMethod(工厂方法模式):2.Abstract Factory(抽象工厂模式):3.Sin ...

  9. Golang 单例模式 singleton pattern

    在Java中,单例模式的实现主要依靠类中的静态字段.在Go语言中,没有静态类成员,所以我们使用的包访问机制和函数来提供类似的功能.来看下下面的例子: package singletonimport ( ...

  10. 单例模式——Singleton

    模式分类: 从目的来看: 1.创建型(Creational)模式:负责对象创建. 2.结构型(Structural)模式:处理类于对象间的组合. 3.行为型(Behavioral)模式:类与对象交互中 ...

最新文章

  1. C# : 调用C++动态库(dll)
  2. win8oracle10g安装报错,Win8电脑安装Oracle 10g提示程序异常终止的解决方法
  3. Chrome跨域问题
  4. 深度学习在美团推荐平台排序中的运用
  5. 每天一个linux命令(性能、优化):【转载】free命令
  6. linux 常用命令及操作
  7. git config设置用户名_git从安装到多账户操作一套搞定(二)多账户使用
  8. linux 文件-s,Linux下访问文件的基本模式
  9. 知乎:全球发售2600万股销售股份 每股发售价51.8港元
  10. python pip安装及出现的问题
  11. Excel2003 使用技巧
  12. Hadoop3集群搭建之——hive添加自定义函数UDTF (一行输入,多行输出)
  13. MySQL的主动优化和被动优化_MySQL“被动”性能优化汇总
  14. linux下rpm包安装jdk,linux jdk rpm包安装
  15. python3多进程执行循环_Python3 并发编程之多进程(一)
  16. java 四则混合运算_Java实现四则混合运算 - Sabrina amp; Joshua Java Ivory Tower - ITeye博客...
  17. java ajax上传文件
  18. 设置后台事务的执行人
  19. 非常优秀的在线绘图网站分享
  20. 计算机主板显卡接口,【我想给电脑加个显卡,但是不知道这个主板的显卡接口是什么类型的?】.请大家帮忙...

热门文章

  1. ubuntu16.04下编译安装OpenCV
  2. 几个方便编程的C++特性
  3. Warning:关于_CRT_SECURE_NO_WARNINGS
  4. 【完全开源】微信客户端.NET版
  5. curl 发送带有Authorization的post请求命令
  6. 单片机IO口模拟串口程序(发送+接收
  7. [电子商务网站设计] 之 My Space
  8. 淘宝Django书籍调研
  9. flask_mail用法实例
  10. ubuntu下面的chrome浏览器增加标题栏