目录

一、什么是单例模式?

二、单例模式的应用场景

三、两种典型的方式实现单例模式

1.饿汉模式

2.懒汉模式

3.理解懒汉模式和饿汉模式

四、单例模式和线程的关系

1.饿汉模式是否线程安全?

2.懒汉模式线程安全吗?为什么?

2.1 如何改进懒汉模式?让代码变得线程安全呢?


一、什么是单例模式?

单例模式是一种常见的“设计模式”

二、单例模式的应用场景

某个类,不应该有多个实例,此时就可以使用单例模式(DataSource就是一个典型的案例,一一个程序中只有一个实例,不应该实例化多个DataSource对象)。如果尝试创建多个实例,编译期就会报错。

三、两种典型的方式实现单例模式

1.饿汉模式

public class singlePattern {//先创建一个表示单例的类//我们就要求Singleton这个类只能有一个实例//饿汉模式的单例实现//饿汉模式的单例实现,“饿”指得是,只要类被加载,实例就会立刻创建(实例创建时机比较早)static class Singleton{//把 构造方法  变为私有,此时在该类外部,就无法 new 这个类的实例了private Singleton(){}
//再来创建一个 static 的成员,表示Singleton 类唯一的实例//static 和 类相关,和实例无关,类在内存中只有一份,static 成员也就只有一份static Singleton instance = new Singleton();//new没报错是因为Singleton类是singlePattern的内部类,singlePattern是可以访问内部类的private成员的public static Singleton getInstance(){return instance;}public static void main(String[] args) {
//此处得 getInstance 就是获取实例得唯一方式,不应该使用其他方式创建实例了Singleton s = Singleton.getInstance();Singleton s2 = Singleton.getInstance();System.out.println(s == s2);}
}}

只要类被加载,就会立刻实例化Singleton实例,后续无论怎么操作,只要严格使用getInstance,就不会出现其他实例。

2.懒汉模式

public class lazyPattern {//使用懒汉模式来实现,Singleton类被加载的时候,不会立刻实例化//等到第一次使用这个实例的时候,再实例化static class Singleton{private static Singleton instance = null;public static Singleton getInstance(){if(instance == null){instance = new Singleton();}return instance;}}public static void main(String[] args) {}
}

类被加载的时候,没有立刻被实例化,第一次调用getInstance的时候,才真正的实例化。

如果要是代码一整场都没有调用getInstance,此时实例化的过程也就被省略掉了,又称“延时加载”

一般认为“懒汉模式” 比 “饿汉模式”效率更高。

懒汉模式有很大的可能是“实例用不到”,此时就节省了实例化的开销。

3.理解懒汉模式和饿汉模式

各种编辑器,有两种主要的打开方式:

  • 记事本,会尝试把整个文件的内容都读取到内存中,然后再展示给用户(饿汉模式)
  • vscode/sublime,只是会把当前这个屏幕内的内容(以及周围的一小点内容)加载到内存中,随着翻页,会继续加载

四、单例模式和线程的关系

1.饿汉模式是否线程安全?

安全。

类加载只有一次机会,不可能并发执行,对于饿汉模式来说,多线程同时调用getInstance,由于getInstance里只做了一件事:读取instance实例的地址=》多个线程在同时读取同一个变量,不会产生线程不安全。

2.懒汉模式线程安全吗?为什么?

懒汉模式是线程不安全的,只有在实例化之前调用,存在线程不安全问题

如果要是已经把实例创建好了~后面再去并发调用getInstance 就是线程安全的了

以上面的懒汉模式代码为例,多线程并发执行的时间线如下。

2.1 如何改进懒汉模式?让代码变得线程安全呢?

1.加锁

public class lazyPatternToSafe {static class Singleton{private static Singleton instance = null;//方法一:public static Singleton getInstance1(){synchronized (lazyPattern.Singleton.class){if(instance == null){instance = new Singleton();}}return instance;}//方法二:synchronized public static Singleton getInstance2(){if(instance == null){instance = new Singleton();}return instance;}}
}

上面的“粒度”较小,下面的“粒度”较大。

加锁之后的时间线:

但是加锁之后,仍然存在效率问题。上面的改进代码,哪怕实例已经创建好了,但是每次调用getInstance还是涉及加锁解锁,而这里的加锁解锁已经不必要了。只要代码中涉及到锁,基本上就和高性能无缘了(因为涉及到锁之间的等待)

2.解决方案:只有在实例化之前调用的时候加锁,后面不加锁~

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

上述双线程执行的时间线如下:

此时即能保证线程安全,也能保证程序运行的效率。

3.但是还是存在问题,此处的多个操作,可能会被编译器优化,只有第一次读才从内存中读取,后续的读就直接从CPU中读取寄存器。就可能导致线程1修改之后,线程2没有读到最新的值,内存可见性导致的线程不安全问题(先加锁的线程在修改,后加锁的线程在读取)。

最终版本:加volatile关键字

static class Singleton {//为了解决内存不可见问题,需要加上关键字volatileprivate volatile static Singleton instance = null;public static Singleton getInstance1() {if(instance == null){synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

上面的代码:为了保证线程安全,涉及到三个要点:

1.加锁 【保证线程安全】

2.双重if 【保证效率】

3.volatile【避免内存可见性引来的问题】

单例模式——饿汉模式懒汉模式相关推荐

  1. DBCP使用BasicdataSource连接(两种单例模式-----饿汉和懒汉模式)

    DBCP使用BasicDataSource连接 BasicDataSource实现DataSource的接口,可以进行简单的数据库连接 第一种:懒汉模式:顾名思义,"懒",只有在调 ...

  2. 单例模式 (饿汉、懒汉)

    单例模式 定义 单例模式的实现 饿汉模式 懒汉模式 线程安全问题分析: 如何解决线程安全问题?? 关键点总结 定义 单例模式,是一种常见的"设计模式" 设计模式: 设计模式是一套经 ...

  3. 单例模式之饿汉、懒汉模式

    目录 1.单例模式 1.1 饿汉模式 1.2 懒汉模式 1.单例模式 单例模式能保证类在程序中只存在唯一一份实例.这一点在很多场景中都需要,比如JDBC中的DataSource实例就只需要一个. 单例 ...

  4. 单例模式之饿汉和懒汉(java)

    文章目录 1.前言 2.怎么区分饿汉和懒汉模式 3. 饿汉 4.懒汉 (双重检查 Double Check Lock) 5.饿汉模式在JDK中的应用(Runtime) 6.相关文章 1.前言 面试时, ...

  5. C++设计模式--单例模式详解(懒汉模式、饿汉模式、双重锁)

    C++设计模式--单例模式详解(懒汉模式.饿汉模式.双重锁) 应用场景 一.单例模式是什么? 二.使用步骤 1.UML图 2.代码实现 应用场景 通常我们在做通讯的时候,我们跟服务器数据交互,假如每次 ...

  6. 单例模式饿汉模式与懒汉模式

    目录 1.什么是单例模式 2.为什么需要单例模式? 3.如何实现单例模式 3.1饿汉方式 3.2懒汉模式 1.什么是单例模式 单例模式是一种设计模式,单例模式能保证某个类在程序中只存在唯一一份实例, ...

  7. 单例模式之饿汉模式懒汉模式

    前言 单例模式能保证某个类在程序中只存在唯一一份实例,而不会创建出多个实例,比如 JDBC 中的 DataSource 实例就只需要一个.单例模式具体的实现方式有"饿汉" 和 &q ...

  8. Singleton模式(单例模式) 饿汉式和懒汉式

    目的:整个应用中有且只有一个实例,所有指向该类型实例的引用都指向这个实例. 好比一个国家就只有一个皇帝(XXX),此时每个人叫的"皇帝"都是指叫的XXX本人; 常见单例模式类型: ...

  9. 单例模式,饿汉与懒汉

    文章目录 什么是单例模式 单例模式的两种形式 饿汉模式 懒汉模式 懒汉模式与饿汉模式是否线程安全 懒汉模式的优化 什么是单例模式 单例模式其实就是一种设计模式,跟象棋的棋谱一样,给出一些固定的套路帮助 ...

  10. Java-Day12 面向对象的三大特征之封装、继承,单例模式(饿汉式、懒汉式)、方法重写 (覆盖)、注解 (annotation)、super关键字、对象的创建流程超详细

    目录 1. 面向对象的三大特征之封装 1.1 封装的含义 1.2 封装的目的 1.3 封装的优点 1.4 封装的实现过程 1.5 拓展知识:JavaBean 2. 面向对象的三大特征之继承 2.1 继 ...

最新文章

  1. linux.调整收发队列,linux消息队列通信
  2. 20165318 结对编程项目-四则运算 阶段总结
  3. sonarqube+jenkins 构建代码质量管理平台
  4. Pandas dtypes
  5. Java基础学习总结(67)——Java接口API中使用数组的缺陷
  6. Android Studio导入so文件到项目中
  7. 2.4 使用ARDUINO控制MC20进行GPS数据的获取和解析
  8. 一、华为设备telnet命令配置
  9. AI头发笔刷_这么棒的AI插件,一定要偷偷藏好了不让总监知道……
  10. Unity制作简单动画效果
  11. Xpose 建立新工程
  12. TA入门笔记(十五)
  13. AIS数据修复-三次样条插值法(Cubic spline interpolation)
  14. 如何下载OpenJDK安装版本
  15. html文字多余部分三个点,解决特殊符号和字母换行问题
  16. VB中ByVal与ByRef有什么区别
  17. 广电电视信号如何生成RTMP流进入流媒体系统网络分发实现手机APP播放
  18. c语言编程杨辉三角形流程图,使用c语言输出杨辉三角形的简单方法
  19. 写给所有程序员的心声~千里马常有,但伯乐不常有
  20. SpringMVC 13. RESTful CRUD

热门文章

  1. canvas 系列学习笔记一《基础》
  2. C#中线程和进程的区别
  3. 网页设计必备资源(ZT)
  4. 网站制作完成后--如何用ttkefu成功接单制作网站实例
  5. 《计算机网络第6版-谢希仁》读书笔记
  6. Python好用的VSCode插件
  7. dw本地文件传不到远程服务器,用DW上传站点 怎么设置远程服务器
  8. YY--MM--DD格式的日期加一天
  9. vscode调试rust
  10. 化工行业B2B网站,未来几年发展重点