单例模式 男娘i 2021-08-29 16:42 310阅读 0赞 ### 单例模式 ### * 1. 简介 * * 1.1 定义 * 1.2 为什么使用单例模式 * 1.3 为什么不使用全局变量确保一个类只有一个实例呢 * 2. 单例的模式的实现 * * 2.1 饿汉式(线程安全) * 2.2 懒汉式(非线程安全和synchronized关键字线程安全版本 ) * 2.3 懒汉式(双重检查加锁版本) * 2.4 懒汉式(静态内部类方式) * 2.5 饿汉式(枚举方式) # 1. 简介 # ## 1.1 定义 ## 保证一个类只有一个实例,并提供一个访问它的全局访问点。 ## 1.2 为什么使用单例模式 ## 在我们的系统中,有一些对象其实我们只需要一个,比如说:线程池、缓存、对话框、注册表、日志对象、充当打印机、显卡等设备驱动程序的对象。事实上,这一类对象只能有一个实例,如果制造出多个实例就可能会导致一些问题的产生,比如:程序的行为异常、资源使用过量、或者不一致性的结果。 **简单来说使用单例模式可以带来下面几个好处:** * 对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销; * 由于 `new` 操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻 `GC` 压力,缩短 `GC` 停顿时间。 ## 1.3 为什么不使用全局变量确保一个类只有一个实例呢 ## 全局变量分为静态变量和实例变量,静态变量也可以保证该类的实例只存在一个。 只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。 但是,如果说这个对象非常消耗资源,而且程序某次的执行中一直没用,这样就造成了资源的浪费。**利用单例模式的话,我们就可以实现在需要使用时才创建对象,这样就避免了不必要的资源浪费**。 不仅仅是因为这个原因,在程序中我们要尽量避免全局变量的使用,大量使用全局变量给程序的调试、维护等带来困难。 # 2. 单例的模式的实现 # 通常单例模式在`Java`语言中,有两种构建方式: * 饿汉方式。指全局的单例实例在类装载时构建 * 懒汉方式。指全局的单例实例在第一次被使用时构建。 不管是那种创建方式,它们通常都存在下面几点相似处: * 单例类必须要有一个 `private` 访问级别的构造函数,只有这样,才能确保单例不会在系统中的其他代码内被实例化; * `instance` 成员变量和 `uniqueInstance` 方法必须是 `static` 的。 ## 2.1 饿汉式(线程安全) ## /** * @author wangzhao * @date 2020/6/6 9:30 */ public class Singleton { // 在静态初始化器中创建单例实例,这段代码保证了线程安全 private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; } } 所谓 “**饿汉方式**” 就是说`JVM`在加载这个类时就马上创建此唯一的单例实例,不管你用不用,先创建了再说,如果一直没有被使用,便浪费了空间,典型的空间换时间,每次调用的时候,就不需要再判断,节省了运行时间。 ## 2.2 懒汉式(非线程安全和synchronized关键字线程安全版本 ) ## /** * @author wangzhao * @date 2020/6/6 9:30 */ public class Singleton { private static Singleton instance = null; private Singleton() { } // 线程不安全,判断 null 和 new 是两个步骤,不具有原子性 public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } “ **懒汉式**” 就是说单例实例在第一次被使用时构建,而不是在`JVM`在加载这个类时就马上创建此唯一的单例实例。 但是上面这种方式很明显是线程不安全的,如果多个线程同时访问`getInstance()`方法时就会出现问题。如果想要保证线程安全,一种比较常见的方式就是在`getInstance()`方法前加上`synchronized`关键字,如下: /** * @author wangzhao * @date 2020/6/6 9:30 */ public class Singleton { private static Singleton instance = null; private Singleton() { } public synchronized static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } 在程序中每次使用`getInstance()`都要经过`synchronized`加锁这一层,这难免会增加`getInstance()`的方法的时间消费,而且还可能会发生阻塞。我们下面介绍到的 双重检查加锁版本 就是为了解决这个问题而存在的。 ## 2.3 懒汉式(双重检查加锁版本) ## 利用双重检查加锁(`double-checked locking`),首先检查是否实例已经创建,如果尚未创建,“才”进行同步。这样以来,只有一次同步,这正是我们想要的效果。 /** * @author wangzhao * @date 2020/6/6 9:30 */ public class Singleton { //volatile保证,当instance变量被初始化成Singleton实例时,多个线程可以正确处理instance变量 private volatile static Singleton instance = null; private Singleton() { } public static Singleton getInstance() { // 检查实例,如果不存在,就进入同步代码块 if (instance == null) { // 只有第一次才彻底执行这里的代码 synchronized (Singleton.class){ // 进入同步代码块后,再检查一次,如果仍是null,才创建实例 if (instance == null){ instance = new Singleton(); } } } return instance; } } ## 2.4 懒汉式(静态内部类方式) ## **静态内部实现的单例是懒加载的且线程安全**。 只有通过显式调用`getInstance`方法时,才会显式装载 `SingletonHolder`类,从而实例化`instance`(只有第一次使用这个单例的实例的时候才加载,同时不会有线程安全问题)。 /** * @author wangzhao * @date 2020/6/6 9:30 */ public class Singleton { private Singleton() { } public static class InnerClass{ private static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return InnerClass.instance; } } ## 2.5 饿汉式(枚举方式) ## 这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。 它更简洁,**自动支持序列化机制,绝对防止多次实例化** (如果单例类实现了`Serializable`接口,默认情况下每次反序列化总会创建一个新的实例对象)。 public enum Singleton { //定义一个枚举的元素,它就是 Singleton 的一个实例 INSTANCE; public void doSomeThing() { System.out.println("枚举方法实现单例"); } } **使用方法:** public class ESTest { public static void main(String[] args) { Singleton singleton = Singleton.INSTANCE; singleton.doSomeThing();//output:枚举方法实现单例 } }
相关 单例模式 http://blog.csdn.net/zhengzhb/article/details/7331369 定义:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实 曾经终败给现在/ 2022年09月25日 15:30/ 0 赞/ 309 阅读
相关 单例模式 class sigle{ protected static $ins = null; public function getIns(){ 深藏阁楼爱情的钟/ 2022年07月20日 20:27/ 0 赞/ 337 阅读
相关 单例模式 简介: 单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在。 许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在 ﹏ヽ暗。殇╰゛Y/ 2022年05月09日 15:46/ 0 赞/ 221 阅读
相关 单例模式 <table> <tbody> <tr> <td style="vertical-align:top;width:.6868in;"> <p style 矫情吗;*/ 2021年11月22日 10:52/ 0 赞/ 362 阅读
相关 单例模式 单例模式 单例模式(SingletonPattern)是java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及 红太狼/ 2021年11月16日 05:30/ 0 赞/ 379 阅读
相关 单例模式 1、懒汉式,线程不安全 是否 Lazy 初始化:是 是否多线程安全:否 实现难度:易 描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有 以你之姓@/ 2021年11月11日 17:44/ 0 赞/ 346 阅读
相关 单例模式 应用场景 1. windows的任务管理器 2. 网站的计数器 3. 应用程序的日志 4. 数据库连接池,因为数据库连接是一种数据库资源。数据库软件系统中使用数据 r囧r小猫/ 2021年11月11日 15:08/ 0 赞/ 412 阅读
相关 单例模式 单例模式有以下特征: 1. 只有一个对象存在 2. 对象的实例化必须在类中实现 一、懒汉模式(线程不安全) package com.kevin; 谁借莪1个温暖的怀抱¢/ 2021年10月01日 07:48/ 0 赞/ 396 阅读
相关 单例模式 1.定义 单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在。 2.实现步骤 1. 将该类的构造方法定义为私有方法,这样其他处 小咪咪/ 2021年09月27日 13:56/ 0 赞/ 472 阅读
相关 单例模式 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。 通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责 Dear 丶/ 2021年09月17日 02:10/ 0 赞/ 407 阅读
还没有评论,来说两句吧...