目录:

  1、单例模式(Singleton Pattern)
  2、概念
  3、饿汉式:不是延迟加载,加载类的时候直接初始化
  4、懒汉式:延迟加载,首次需要使用的时候在实例化,需要考虑线程安全
  5、静态内部类实现
  6、枚举实现

1、单例模式(Singleton Pattern)   <==返回目录

    确保一个类只有一个实例,并提供一个全局访问点。

2、概念   <==返回目录

下面的内容转载自博客: 23种设计模式之单例模式 ( https://chenmingyu.top/design-singleton/)

  单例模式:单例模式属于创建型模式;

  定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。单例模式目的是保证在程序运行期间一个类只有一个实例,并提供一个全局访问点,无论什么情况下,只会生成一个实例,免去繁琐的创建销毁对象的过程。

  优点:

)减少了内存开支,避免频繁地创建、销毁对象;
)避免对资源的多重占用;

  缺点:

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化

  如何设计单例模式

    如何设计单例模式其实很简单,只需要考虑一个问题,实例是否可以保证是全局唯一。关于实例是否保证是全局唯一延伸出的问题:

是否线程安全,不安全肯定就不能保证全局只有一个实例
是否支持序列化,支持序列化的类,被反序列化之后肯定就不是全局唯一了
是否支持反射,支持反射肯定也不是全局唯一的
是否可以被克隆,这个也不能保证全局唯一

 

  所以设计一个安全的单例需要考虑的问题还是很多的。针对上述问题常见的解决办法:

保证线程安全,使用volatile+synchronized实现
防止序列化攻击,重写readResolve方法
防止反射,常用的方案是在单例类里增加一个boolean类型的flag标识,在实例化的时候先判断flag标识
防止克隆,重写clone()方法

  

  实现一个最简单的单例就需要考虑到以上的所有问题,这个时候什么有用的方法还没写那,代码就已经很多了,那有没有简单的办法既满足上述条件,代码又简洁那,那肯定有,使用枚举实现单例。

  常见的单例模式实现

常见的单例模式实现方案大概有五种,懒汉模式,饿汉模式,双重检查方式实现,静态内部类实现,枚举实现

  分个类:

是否支持延迟加载,分为懒汉模式和饿汉模式
线程安全设计了双重检查模式实现,静态内部类实现方式
不支持序列化,反射,克隆,枚举实现方式

  其中懒汉模式,饿汉模式,双重检查方式实现,静态内部类的实现方式都可以概括为以下两步:

  1.构造函数私有化,保证在外部无法new对象
  2.提供一个static方法获取当前实例(不同方案,实现不同)

  

  当然枚举的实现方式最简单,也最安全的,所以推荐使用枚举实现,其次推荐使用静态内部类方式实现。

3、饿汉式:不是延迟加载,加载类的时候直接初始化   <==返回目录

优点:线程安全,代码简单。

缺点:不是延迟加载,如果你用不到这个类,它也会实例化,还有一个问题就是如果这个实例依赖外部一些配置文件,参数什么的,在实例化之前就要获取到,否则就实例化异常

/**
* 单例模式:饿汉式
* @author oy
* @date 2019年9月3日 下午11:13:49
*/
public class Singleton { private static Singleton singleton = new Singleton(); private Singleton() {
} public static Singleton getInstance(){
return singleton;
}
}

4、懒汉式:延迟加载,首次需要使用的时候在实例化,需要考虑线程安全   <==返回目录

  线程不安全的实现方式:

/**
* 单例模式:懒汉式,线程不安全
* @author oy
* @date 2019年9月3日 下午11:15:47*/
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static Singleton getInstance(){
if(null == singleton){
singleton = new Singleton();
}
return singleton;
}
}

  线程安全的实现方式:双重检查(DCL:Double Check Lock)

/**
* 单例模式:双重检查(DCL:Double Check Lock)
* @author oy
* @date 2019年9月3日 下午11:17:06
*/
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {} public static Singleton getInstance(){
if(null == singleton){
synchronized (Singleton.class){
if(null == singleton){
singleton = new Singleton();
}
}
}
return singleton;
}
}

  面试题:为什么使用volatile修饰singleton变量?

1.说的volatile,首先肯定回答volatile的可见性
2.防止重排序优化,如果不用volatile修饰,多线程的情况下,可能会出现线程A进入synchronized代码块,
执行new Singleton();,首先给singleton分配内存,但是还没有初始化变量,
这时候线程B进入getInstance方法,进行第一个判断,此时singleton已经不为空,
直接返回singleton,然后肯定报错。使用volatile修饰之后禁止jvm重排序优化,所以就不会出现上面的问题

5、静态内部类实现   <==返回目录

  使用静态内部类实现也是延迟加载,利用静态内部类去实现线程安全,只有在第一次调用getInstance方法的时候才会去加载SingletonHolder,初始化SINGLETON

/**
* 单例模式:静态内部类实现
* @author oy
* @date 2019年9月3日 下午11:17:06
*/
public class Singleton { private Singleton() {} public static Singleton getInstance() {
return SingletonHolder.SINGLETON;
} private static class SingletonHolder {
private static final Singleton SINGLETON = new Singleton();
}
}

6、枚举实现   <==返回目录

  枚举实现代码更简洁,线程安全,并且保证枚举不会被反序列化,反射和克隆

/**
* 单例模式:枚举实现
* @author oy
* @date 2019年9月3日 下午11:17:06
*/
public enum Singleton { SINGLETON; /**
* 提供的方法
*/
public void method() {
System.out.println("枚举实现");
}
}

head first 设计模式笔记5-单例模式的更多相关文章

  1. php设计模式笔记:单例模式

    php设计模式笔记:单例模式 意图: 保证一个类仅有一个实例,并且提供一个全局访问点 单例模式有三个特点: 1.一个类只有一个实例2.它必须自行创建这个实例3.必须自行向整个系统提供这个实例 主要实现 ...

  2. Head First 设计模式笔记:单例模式

    单例模式 确保一个类只有一个实例,并提供一个全局访问点. 类图: Singleton static uniqueInstance //其他属性... static getInstance() //其他 ...

  3. IOS设计模式浅析之单例模式(Singleton)

    说在前面 进入正式的设计模式交流之前,扯点闲话.我们在项目开发的过程中,经常会不经意的使用一些常见的设计模式,如单例模式.工厂方法模式.观察者模式等,以前做.NET开发的时候,认真拜读了一下程杰老师的 ...

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

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

  5. Java设计模式之《单例模式》及应用场景

    摘要: 原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6510196.html 所谓单例,指的就是单实例,有且仅有一个类实例,这个单例不应该 ...

  6. Java设计模式之【单例模式】

    Java设计模式之[单例模式] 何为单例 在应用的生存周期中,一个类的实例有且仅有一个 当在一些业务中需要规定某个类的实例有且仅有一个时,就可以用单例模式 比如spring容器默认初始化的实例就是单例 ...

  7. Java设计模式中的单例模式

    有时候在实际项目的开发中,我们会碰到这样一种情况,该类只允许存在一个实例化的对象,不允许存在一个以上的实例化对象,我们将这种情况称为Java设计模式中的单例模式.设计单例模式主要采用了Java的pri ...

  8. Java设计模式学习笔记(单例模式)

    最近一直在看<Head First设计模式>,这本书写的确实是很不错的,专注于怎么用最简单的方式最通俗的语言让人了解设计模式.据说GoF的设计模式那本书写的很好,是一本经典,但是就是难懂, ...

  9. Java设计模式学习笔记(五) 单例模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 使用单例模式的原因 以Windows任务管理器为例,在Windows系统中,任务管理器是唯 ...

  10. PHP 设计模式 笔记与总结(6)基础设计模式:工厂模式、单例模式和注册树模式

    三种基础设计模式(所有面向对象设计模式中最常见的三种): ① 工厂模式:使用工厂方法或者类生成对象,而不是在代码中直接new 在 Common 目录下新建 Factory.php: <?php ...

随机推荐

  1. 配置Tomcat时退出就自动还原问题

    因为出现中文乱码问题需要配置server.xml文件,可是在每次配置完并且保存的情况下,重启服务器再看server.xml文件时,它自动还原到了未修改前的配置,后,解决如下: 第一步:打开eclips ...

  2. SpringBoot 使用Mybatis操作mysql示例

    1.准备数据库 创建数据库 create databases baodanjia; 创建帐号 create user 'baodanjia'@'%' identified by '123456' gr ...

  3. [python] 进度条效果

    method 1 如果出现多行显示,添加选项 tqdm(iter,ncols=40) """ ncols : int, optional The width of the ...

  4. 初步了解autoencoder

    初步了解autoencoder 学习自莫烦python 什么是autoencoder? 自编码(autoencoder)是一种神经网络的形式. 例子:一张图片->对其进行打码->最后再将其 ...

  5. 关于__name__=='__main__'的理解

    一.总的来说,如果__name__=='__main__'成立,表示当前模块就是主程序, 如果__name__=='__main__'不成立,表示当前模块是被导入到某个模块中的,而此时__name__ ...

  6. 33.服务之间的调用之RPC、Restful深入理解

    33.服务之间的调用之RPC.Restful深入理解 2018年05月08日 01:52:42 郑学炜 阅读数 13577更多 分类专栏: 6.框架   版权声明:本文为博主原创文章,遵循CC 4.0 ...

  7. 数据绑定-@RequestParam

    @PathVariable,前面已经讲过了 @RequestParam 作用:获取请求中的参数,GET请求,问号后面的请求参数,POST:请求体中的KV数据. 测试:

  8. 优秀java博客

    https://www.jianshu.com/p/efb58b7115bf?utm_source=tuicool https://www.nowcoder.com/discuss/110317 ht ...

  9. Linux scp命令详解(服务器之间复制文件或目录)

    scp:服务器之间复制文件或目录 一.命令格式: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] [-l limit] ...

  10. 【Activiti】为每一个流程绑定相应的业务对象的2种方法

    方式1: 在保存每一个流程实例时,设置多个流程变量,通过多个流程变量的组合来过滤筛选符合该组合条件的流程实例,以后在需要查询对应业务对象所对应的流程实例时,只需查询包含该流程变量的值的流程实例即可. ...