一. 定义与类型

定义:保证一个类仅有一个实例,并提供一个全局访问点

类型:创建型

二. 适用场景

想确保任何情况下都绝对只用一个实例

三. 优缺点

优点:

在内存里只有一个实例,减少了内存开销

可以避免对资源的多重占用

设置全局访问点,严格控制访问

缺点:

没有接口,扩展困难

四. 重点

私有构造器

线程安全

延迟加载

序列化和反序列化安全

反射

实用技能:反编译,内存原理,多线程Debug

五. 相关设计模式

单例模式和工厂模式

单例模式和享元模式

六. Coding

懒汉式:

/**
* @program: designModel
* @description: 懒汉单例,懒汉式注重的就是延迟加载,当在使用到这个实例的时候才会初始化
* @author: YuKai Fan
* @create: 2018-12-04 14:04
**/
public class LazySingleton {
private static LazySingleton lazySingleton = null;
private LazySingleton() { }
//如果只有这种方法,是线程不安全的。
//在多线程环境下,使用这个方法,会有概率的产生不止一个实例的情况,虽然最后返回的还是同样的独享
/*public static LazySingleton getInstance() {
if (lazySingleton == null) {
lazySingleton = new LazySingleton();
}
return lazySingleton;
}*/ //在方法上加锁,让这个方法每次只能有一个线程访问
/*public synchronized static LazySingleton getInstance() {
if (lazySingleton == null) {
lazySingleton = new LazySingleton();
}
return lazySingleton;
}*/ //在代码块上加锁,让这个方法每次只能有一个线程访问,这样只会产生一个实例
//这种方式,锁的是class类,存在加锁和解锁的开销,对性能有一定影响
public static LazySingleton getInstance() {
synchronized(LazySingleton.class) {
if (lazySingleton == null) {
lazySingleton = new LazySingleton();
}
}
return lazySingleton;
}
}

如上方代码注释所说,懒汉式的注重点是延时加载,但是在性能和安全方面都所有影响,所以引出下面的双重检查模式

/**
* @program: designModel
* @description: 懒汉式双重检查。既符合延迟加载,也保证了安全性能
* @author: YuKai Fan
* @create: 2018-12-04 14:35
**/
public class LazyDoubleCheckSingleton {
//volatile关键字,使用解决了程序的重排序问题,即使在多线程的情况下,实例变量始终是最新的状态
//使用这种方法是不让下面的2,3发生重排序
private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;
private LazyDoubleCheckSingleton() { }
public static LazyDoubleCheckSingleton getInstance() {
if (lazyDoubleCheckSingleton == null) {
synchronized (LazyDoubleCheckSingleton.class) {
if (lazyDoubleCheckSingleton == null) {
//1.分配内存给这个对象
//2.初始化对象
//3.设置LazyDoubleCheckSingleton 只向刚分配的内存地址
//其中2和3的顺序可能会被颠倒,倒置,判断为null的时候,已经初始化对象,此时并不为空
//intra-thread semantics 不会改变单线程程序的重排序
lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
}
}
}
return lazyDoubleCheckSingleton;
}
}

双重检查,顾名思义是对实例的是否创建做了两层的判断,例如,当thread0,进入getInstance(),此时lazyDoubleCheckSingleton==null,两层的判断都会过,当刚刚走到new LazyDoubleCheckSingleton()时,thread1进入方法时,第一次判断其实lazyDoubleCheckSingleton还是为null,所以会通过,但是由于后面代码加锁,所以无法进入,当thread0执行玩方法时,释放锁,让thread1拿到,在进行判断,此时lazyDoubleCheckSingleton != null,就会直接退出,这样保证了在多线程环境下,始终只有一个实例。

刚开始的时候,我一直认为这样多此一举,为什么要在加锁的外面在判断一次。后来思考明白了,thread0,thread1的执行顺序,以及执行方法的时机在真正的环境下其实是不知道的,由操作系统来决定的。所以有可能是在thread0已经拿到实例的时候,此时thread1才进入方法,这时候这个判断就会不成立,也就不会在获取锁和释放锁,也就提高了程序的性能。

从上面的代码注释可知,这种方式存在重排序的问题,上面解决重排序的问题是使用volatile关键字,来防止重排序,还有一种方式是可以重排序,但是thread1,不会看到。

/**
* @program: designModel
* @description: 使用静态内部类来防止多线程环境下对DoubleCheck的懒汉式单例模式的判断实例问题,同时也允许重排序
* @author: YuKai Fan
* @create: 2018-12-04 16:35
**/
public class StaticInnerClassSingleton {
//使用静态内部类,是基于class对象的初始化锁的延迟加载方式,在线程0执行方法时会去实例,即使发生重排序,线程1也会被锁在初始化阶段
private static class InnerClass{
private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance() {
return InnerClass.staticInnerClassSingleton;
}
private StaticInnerClassSingleton() { }
}

饿汉式:

这是一个很简单的单例模式的方式,它与懒汉式的最大的区别就是延时加载。饿汉式单例模式是在程序加载的时候,就创建实例,但是如果不用该实例,就会占用资源

/**
* @program: designModel
* @description: 饿汉式,与懒汉式最大的区别,就是延时加载,但是饿汉式如果不用该实例,会占用资源
* @author: YuKai Fan
* @create: 2018-12-04 16:57
**/
public class HungrySingleton implements Serializable {
private final static HungrySingleton hungrySingleton; static {
hungrySingleton = new HungrySingleton();
}
private HungrySingleton() { }
public static HungrySingleton getInstance() {
return hungrySingleton;
} private Object readResolve() {
return hungrySingleton;
}
}

单线程的执行顺序

多线程的执行顺序

java设计模式——单例模式(一)的更多相关文章

  1. java设计模式单例模式 ----懒汉式与饿汉式的区别

    常用的五种单例模式实现方式 ——主要: 1.饿汉式(线程安全,调用率高,但是,不能延迟加载.) 2.懒汉式(线程安全,调用效率不高,可以延时加载.) ——其他: 1.双重检测锁式(由于JVM底层内部模 ...

  2. Java设计模式の单例模式

    -------------------------------------------------- 目录 1.定义 2.常见的集中单例实现 a.饿汉式,线程安全 但效率比较低 b.单例模式的实现:饱 ...

  3. JAVA设计模式-单例模式(Singleton)线程安全与效率

    一,前言 单例模式详细大家都已经非常熟悉了,在文章单例模式的八种写法比较中,对单例模式的概念以及使用场景都做了很不错的说明.请在阅读本文之前,阅读一下这篇文章,因为本文就是按照这篇文章中的八种单例模式 ...

  4. Java设计模式 - - 单例模式 装饰者模式

    Java设计模式 单例模式 装饰者模式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 静态代理模式:https://www.cnblogs.com/StanleyBlogs/p/1 ...

  5. 【设计模式】Java设计模式 - 单例模式

    [设计模式]Java设计模式 - 单例模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 分享学习心得,欢迎指正,大家一起学习成长! 原创作品,更多关注我CSDN: ...

  6. Java 设计模式 —— 单例模式

    1. 概念: 单例模式是一种常用的软件设计模式.核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果 ...

  7. Java设计模式 - 单例模式 (懒汉方式和饿汉方式)

    概念: Java中单例模式是一种常见的设计模式,单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的写法有好几种,这 ...

  8. JAVA设计模式--单例模式

    单例设计模式 Singleton是一种创建型模式,指某个类采用Singleton模式,则在这个类被创建后,只可能产生一个实例供外部访问,并且提供一个全局的访问点. 核心知识点如下: (1) 将采用单例 ...

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

    单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1.某些类创建比较频繁,对于一些大型的对象,这是一笔 ...

随机推荐

  1. 单机部署zookeeper、kafka

    先安装jdk:mkdir /usr/javatar xf jdk-8u151-linux-x64.tar.gzmv jdk1.8.0_151/ /usr/java/jdk1.8 cat /etc/pr ...

  2. 11gR2 ASM RAC + ASM RAC dataguard配置

    1.环境说明 --primary端配置 Primary RAC Node1 Node2 Public IP 192.168.56.120 192.168.56.122 Private IP 10.0. ...

  3. Meter - 连续性能测试 - JMeter + ANT + Jenkins集成 - 第1部分

    目标: 创建包含性能测试流程的持续交付管道, 以尽早检测任何与性能相关的问题. 通常,全面的性能测试将在分段/预生产环境中完成,该环境可能与您的生产环境相同.在完成QA功能/回归验证后,将代码推送到分 ...

  4. vuex和localStorage/sessionStorage 区别

    1.最重要的区别:vuex存储在内存,localstorage则以文件的方式存储在本地 2.应用场景:vuex用于组件之间的传值,(响应式的),localstorage则主要用于不同页面之间的传值(其 ...

  5. Scrapy框架中的Pipeline组件

    简介 在下图中可以看到items.py与pipeline.py,其中items是用来定义抓取内容的实体:pipeline则是用来处理抓取的item的管道 Item管道的主要责任是负责处理有蜘蛛从网页中 ...

  6. Navicat连接MySQL数据库的一些问题与解决方案

    前言 安装MySQL数据库与Navicat并不算难事,关键是怎么让他们工作花费了我整整一天的时间,最终才把弄好.遇到各种各样的问题,上网看了大量博客,发现很多博客都是直接copy或者并不能非常好的解答 ...

  7. Proxy opening connection toSpringClound配置豪猪hystrixDashboard发生

    Proxy opening connection to: http://localhost:8001/hystrix.stream 配置hystrixDashboard发生的错误.一直在寻找 最后发现 ...

  8. Visitor模式(访问者设计模式)

    Visitor ? 在Visitor模式中,数据结构与处理被分离开来.我们编写一个表示"访问者"的类来访问数据结构中的元素, 并把对各元素的处理交给访问者类.这样,当需要增加新的处 ...

  9. Word中图片自动编号且与文中引用的编号对应

    当我们在进行大篇幅 word 文档的编写时, 为了节约修改文章中图片所花费的大量时间, 可以将图片自动编号,且让文中引用的顺序跟着图片顺序的变化而变化,具体操作如下: 1. 将鼠标定在欲加编号的下方, ...

  10. js固定两位小数toFixed(2)

    total=total.toFixed(3); 小数问题:可以number(),或者*1来改变变量类型.