java设计模式之单例模式你真的会了吗?(懒汉式篇)

一、什么是单例模式?

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

二、单例模式之懒汉式有什么特点以及优缺点?

  • 构造方法私有化
  • 在第一次被使用时构建实例,延迟初始化
  • 对外提供统一的静态工厂方法返回实例
  • 优点:需要的时候才实例化所以节约内存。
  • 缺点:第一次加载时不够快,多线程使用时不必要的同步开销大。

三、懒汉式单例的代码进阶(1)

public class LazySingleton implements Serializable {
private static final long serialVersionUID = -777413485350310911L; private LazySingleton() {} private static LazySingleton lazySingleton = null; public static LazySingleton getInstance() {
if(lazySingleton == null){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
  • 上面的代码存在着最明显的问题就是在多线程的环境下无法保证单例。

四、懒汉式单例的代码进阶(2)

public class LazySingleton implements Serializable {
private static final long serialVersionUID = -777413485350310911L; private LazySingleton() {} private static LazySingleton lazySingleton = null; synchronized public static LazySingleton getInstance() {
if(lazySingleton == null){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
  • 上面的代码在getInstance()方法前面增加了关键字synchronized进行线程锁,以处理多个线程同时访问的问题。但是,这样虽然解决了线程安全问题,但是每次调用getInstance()时都需要进行线程锁定判断,在多线程高并发访问环境中,将会导致系统性能大大降低。

五、懒汉式单例的代码进阶(3)

public class LazySingleton implements Serializable {
private static final long serialVersionUID = -777413485350310911L; private LazySingleton() {} private static LazySingleton lazySingleton = null; //double check
public static LazySingleton getInstance() {
if(lazySingleton == null){
synchronized(LazySingleton.class){
if(lazySingleton == null){
lazySingleton = new LazySingleton();
}
}
}
return lazySingleton;
}
}
  • 上面的代码采用synchronized和double check的方式成功解决了线程安全问题以及提高了多线程下的性能,但是性能任然不够理想。

六、懒汉式单例的代码进阶(4)

public class LazySingleton implements Serializable {
private static final long serialVersionUID = -777413485350310911L; private LazySingleton() {} public static LazySingleton getInstance() {
return LazyInnerSingleton.INSTANCE;
} /**
* 利用内部类的特性创建单例
*/
private static class LazyInnerSingleton {
private static final LazySingleton INSTANCE = new LazySingleton();
}
}
  • 上面利用内部类的特性创建单例既保证了线程安全(由jvm的类加载机制提供)问题又提高了性能,但是还是存在着一个问题:利用反射依然可以破坏“单例”,所以继续改进代码。

六、懒汉式单例的代码进阶(5)

public class LazySingleton implements Serializable {
private static final long serialVersionUID = -777413485350310911L; private LazySingleton() {
//防止利用反射破坏单例
if(LazyInnerSingleton.INSTANCE != null){
throw new RuntimeException("不允许构建多个实例!");
}
} public static LazySingleton getInstance() {
return LazyInnerSingleton.INSTANCE;
} /**
* 利用内部类的特性创建单例
*/
private static class LazyInnerSingleton {
private static final LazySingleton INSTANCE = new LazySingleton();
}
}
  • 在构造方法中抛出一个异常以防止通过反射破坏单例。

PS:如果你看到了这篇文章,并且觉得对你有帮助,请给个关注和点赞,谢谢!

java设计模式之单例模式你真的会了吗?(懒汉式篇)的更多相关文章

  1. java 设计模式之单例模式

    -------Success is getting what you want, happiness is wanting what you get. java设计模式之单例模式(Singleton) ...

  2. 折腾Java设计模式之单例模式

    博文原址:折腾Java设计模式之单例模式 单例模式 Ensure a class has only one instance, and provide a global point of access ...

  3. Java设计模式之单例模式(七种写法)

    Java设计模式之单例模式(七种写法) 第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: public class Singleton { private static Singleto ...

  4. Java 设计模式之单例模式(一)

    原文地址:Java 设计模式之单例模式(一) 博客地址:http://www.extlight.com 一.背景 没有太多原由,纯粹是记录和总结自己从业以来经历和学习的点点滴滴. 本篇内容为 Java ...

  5. java设计模式1——单例模式

    java设计模式1--单例模式 1.单例模式介绍 1.1.核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点 1.2.常见场景 1.3.单例模式的优点 1.4.常见的五种单例模式实现 ...

  6. java设计模式之单例模式(几种写法及比较)

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  7. java设计模式- (1)单例模式

    参加校园招聘的笔试,发现公司都会考一些java设计模式,所以上网查询相关内容,总结常用的几种单例模式. 单例模式(Singleton Pattern)是 Java中最简单的设计模式之一.这种类型的设计 ...

  8. [转]JAVA设计模式之单例模式

    原文地址:http://blog.csdn.net/jason0539/article/details/23297037 概念: java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主 ...

  9. java设计模式之单例模式(七种方法)

    单例模式:个人认为这个是最简单的一种设计模式,而且也是在我们开发中最常用的一个设计模式. 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个 ...

随机推荐

  1. python那些需要知道的事儿——逻辑运算与比大小

    一.逻辑运算 逻辑运算符: and   or   not,结果为布尔值(True和False) 1.基本逻辑运算符介绍 not :将后面的逻辑运算结果取反 >>> not 1 < ...

  2. java例题_25 判断是否为回文数!

    1 /*25 [程序 25 求回文数] 2 题目:一个 5 位数,判断它是不是回文数.即 12321 是回文数,个位与万位相同,十位与千位相同. 3 */ 4 5 /*分析 6 * 先用%和/将5个数 ...

  3. Redis 超详细的手动搭建Cluster集群步骤

    功能概述 ​ Redis Cluster是Redis的自带的官方分布式解决方案,提供数据分片.高可用功能,在3.0版本正式推出. ​ 使用Redis Cluster能达到负载均衡的问题,内部采用哈希分 ...

  4. 最短路径(Dijskra算法)

    声明:图片及内容基于:https://www.bilibili.com/video/BV16C4y1H7Zc?from=articleDetail 最短路径 Dijkstra算法 原理 数据结构 核心 ...

  5. Redis 6.1 redis-cluster-proxy 实践说明

    背景 ​ Redis3.0版本之后开始支持了Redis Cluster,Redis也开始有了分布式缓存的概念.关于Redis Cluster的相关说明,可以看之前的几篇文章:Redis Cluster ...

  6. Linux 常用系统性能命令总结

    Linux 常用系统性能命令 查看系统负载top,free **w/uptime  ** 最后面三个数字表示1分钟,5分钟,15分钟平均有多少个进程占用CPU占用CPU的进程可以是Running,也可 ...

  7. Python中切片的应用

    Python中切片的应用 Python中可以通过切片实现对列表或者字符串取指定范围的操作,实际就是通过对列表或者字符串通过索引进行操作. 具体细节点击廖雪峰Python教程,其中的课后小问题在此记录下 ...

  8. OO_Unit4暨学期总结

    OO_Unit4暨学期总结 一.本单元架构设计 1.1 第13次作业架构设计 就我个人而言,这次作业应该是本单元难度最大的一次作业,原因在于陡然转向UML后,对UML各个元素的关系理解需要先下一番功夫 ...

  9. 数据库MySQL三

    进阶4:常见函数 字节长度为12,一个汉字3个字节 8个字符 注意起始索引 1 -1 0 红色是记忆的 二.数学函数 当前日期包括时间 获取日期 获取时间 四.流程控制函数 案例 分组函数 单行函数: ...

  10. Java执行groovy脚本的两种方式

    记录Java执行groovy脚本的两种方式,简单粗暴: 一种是通过脚本引擎ScriptEngine提供的eval(String)方法执行脚本内容:一种是执行groovy脚本: 二者都通过Invocab ...