博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
单例模式
阅读量:4337 次
发布时间:2019-06-07

本文共 2111 字,大约阅读时间需要 7 分钟。

单例模式

这个设计模式应该算是我最早接触到一个,也是从那个时候知道有一种东西叫设计模式,看到这种代码结构,有种将好的东西通过某种精美的包装进行包装一样,似锦上添花。

单例模式:单例模式中有一个单例类的结构,来保证系统中,该类只能够被实例化一个,通过这种方式控制系统中实例的个数,同时易于外界访问。

为什么使用单例模式

对于缓存,数据库连接,网络请求队列等,资源消耗比较大的,通常我们只是需要一个实例,来减少资源的消耗。

为什么不实用静态全局变量来进行控制呢?
通过静态全局变量持有一个我们创建的实例,然后对这个实例进行一些操作不也是可以保证单例吗?这种方式似乎要比多出一个设计模式去改变类的结构方便的多,但是我们却不会这样去做,原因就是

  1. 当我们设置一个全局的变量在系统中,其会导致出现命名空间污染现象,导致我们在一些引用的过程中,出现了将全局变量作为局部变量使用的情况,

  2. 同时如果我们对于静态全局变量如果不加锁的话,很容易在多线程操作的过程中带来同步上的一些问题,

  3. 最后一个原因就是如果我们将其作为一个静态全局变量使用,那么我们就无法实现一个惰性创建实例,对于过于消耗资源的实例,通过惰性创建,我们将其拖延至使用时创建,而不会过早的消耗资源。

单例模式的实际应用

到了看一下单例模式庐山真面目的时候了,首先通过一段简单的Java代码看一下其大体结构。

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

上面是一个简单单例模式的示范代码,通过这个代码,我们可以看出单例类的构造方法是私有方法,也就是该类我们没有办法通过new得到的,只能够通过 静态的getInstance()方法得到。但是对于多线程问题,如果有多个线程在执行这个方法,那么可能就会有多个实例被创建出来,如何应对这个问题 呢?

1.对该代码区域进行同步

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

当我们对代码块进行加锁之后,一个线程就要等到另一个线程结束之后,才可以继续执行该区域代码,但是当我们对一个代码区域进行加锁之后,我们的代码效率就会降低100倍。对这个代码区域进行同步之后,每当我们执行这块代码,都将会出现一个等待。

2.急切创建实例,而不是采用惰性创建

public class Singleton{ private static Singleton mSingleton = new Singleton(); private Singleton(){ } public synchronized Singleton static getInstance(){ return mSingleton; } }

通过急切创建在对类进行初始化的时候就实例化了类,就不会出现多个线程竞争的问题,但是会导致的问题是如果创建实例消耗过大的时候就会出现提前消耗资源的问题。因此我们常采用的一种方法是双重加锁法。

3.双重检查加锁

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

这种方式对于加锁不是对整个方法进行加锁,而是判断当这个单例未被初始化之后,才对这个实例的初始化区域进行一个同步,在同步的过程中在进行一个是 否实例化的判断。即所谓的双重检查。课有疑问的在于,我们已经进入了同步区域了,为什么还要对其做一个判断呢?就是当两个线程同时越过了第一个判断之后, 如果我们在同步方法中没有对与实例的判断,这个时候,我们就有可能出现实例被创建两次的情况。

综上所述:综合效率,资源消耗等来看,通过双重检查加锁的方式来创建最为方便。

转载于:https://www.cnblogs.com/xubiao/p/5498850.html

你可能感兴趣的文章
阶段3 2.Spring_02.程序间耦合_5 编写工厂类和配置文件
查看>>
阶段3 2.Spring_01.Spring框架简介_05.spring的优势
查看>>
阶段3 2.Spring_02.程序间耦合_7 分析工厂模式中的问题并改造
查看>>
阶段3 2.Spring_02.程序间耦合_4 曾经代码中的问题分析
查看>>
阶段3 2.Spring_03.Spring的 IOC 和 DI_2 spring中的Ioc前期准备
查看>>
阶段3 2.Spring_03.Spring的 IOC 和 DI_4 ApplicationContext的三个实现类
查看>>
阶段3 2.Spring_02.程序间耦合_8 工厂模式解耦的升级版
查看>>
阶段3 2.Spring_03.Spring的 IOC 和 DI_6 spring中bean的细节之三种创建Bean对象的方式
查看>>
阶段3 2.Spring_04.Spring的常用注解_2 常用IOC注解按照作用分类
查看>>
阶段3 2.Spring_09.JdbcTemplate的基本使用_5 JdbcTemplate在spring的ioc中使用
查看>>
阶段3 3.SpringMVC·_07.SSM整合案例_02.ssm整合之搭建环境
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_3、快速创建SpringBoot应用之手工创建web应用...
查看>>
阶段3 3.SpringMVC·_07.SSM整合案例_04.ssm整合之编写SpringMVC框架
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_5、SpringBoot2.x的依赖默认Maven版本...
查看>>
阶段3 3.SpringMVC·_07.SSM整合案例_08.ssm整合之Spring整合MyBatis框架
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_9、SpringBoot基础HTTP其他提交方法请求实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_12、SpringBoot2.x文件上传实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_19、SpringBoot个性化启动banner设置debug日志...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_20、SpringBoot2.x配置全局异常实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第5节 SpringBoot部署war项目到tomcat9和启动原理讲解_23、SpringBoot2.x启动原理概述...
查看>>