关于单例模式:

单例,即单一实例。因为在一些情况下,某些类的对象,我们只需要一个就可以了,所以我们要用到单例模式。

单例模式的目的是使得一个类中的一个静态对象成为系统中的唯一实例,提供一个访问该实例的方法。并阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。

单例模式特点:其在整个应用程序的生命周期中只存在一个实例。

单例模式分为懒汉式和饿汉式两种

这里先贴出代码,然后再做解释,便于理解。

懒汉式单例模式核心代码:

 1 package com.wxb.singleton;
2
3 public class Singleton_Lazy {
4 /* --创建私有静态的自身实例对象-- */
5 private static Singleton_Lazy uniqueInstance = null;
6
7 /* --私有的构造方法,避免外界利用构造方法创建多个实例-- */
8 private Singleton_Lazy() {
9
10 }
11
12 /* --获取静态实例的方法--
13 * --该方法是静态的,可以通过类名直接调用--
14 */
15 public static Singleton_Lazy getUniqueInstance() {
16 if (null == uniqueInstance) {
17 uniqueInstance = new Singleton_Lazy();
18 }
19 return uniqueInstance;
20 }
21 }

懒汉式单例模式特点:懒汉模式的单例类的唯一实例对象是在第一次使用 getUniqueInstance()时实例化的。如果我们不调用 getUniqueInstance()的话,这个实例是不会存在的,即为 初始值null。可以看出如果不去动它的话,它自己是不会实例化的,所以形象的称之为懒汉模式。

饿汉式单例模式核心代码:

 1 package com.wxb.singleton;
2
3 public class Singleton_Hungry {
4 /*
5 * --在初始化时,就实例化了静态的自身实例对象-- --饿汉式的缺点也在于此:浪费内存--
6 */
7 private static Singleton_Hungry uniqueInstance = new Singleton_Hungry();
8
9 /* --私有的构造方法,避免外界利用构造方法创建多个实例-- */
10 private Singleton_Hungry() {
11
12 }
13
14 /* --获取静态实例的方法--
15 * --该方法是静态的,可以通过类名直接调用--
16 */
17 public static Singleton_Hungry getUniqueInstance() {
18 return uniqueInstance;
19 }
20 }

饿汉单例模式特点:之所以称之为饿汉,是因为肚子饿了,人也会变得主动了,所以饿汉模式下的单例类其自己就会主动实例化该单例类的唯一实例对象。

一般懒汉式单例模式较为常用。

对于唯一实例的验证:

 1 package com.wxb.singleton;
2
3 public class SingletonTest {
4 /* --单例模式唯一实例的测试|调用懒汉式单例验证-- */
5 public static void main(String[] args) {
6 Singleton_Lazy singleton_Lazy1 = Singleton_Lazy.getUniqueInstance();
7 Singleton_Lazy singleton_Lazy2 = Singleton_Lazy.getUniqueInstance();
8 if (singleton_Lazy1.equals(singleton_Lazy2)) {
9 System.out.println("Singleton_Lazy1 and singleton_Lazy2 are the same instance");
10 }
11 else {
12 System.out.println("Singleton_Lazy1 and singleton_Lazy2 are different instance");
13 }
14 }
15 }

输出结果:

可以看出虽然两次调用getUniqueInstance(),但是访问的是同一个实例。

对于懒汉式单例模式,还存在着多线程安全问题

在多线程中,如果在一开始调用 GetUniqueInstance()时,是由两个线程同时调用的,这样的话,两个线程均会进入GetUniqueInstance(),而后由于是第一次调用 GetUniqueInstance(),所以静态变量 uniqueInstance为 null ,这样的话,就会让两个线程均通过 if 语句的条件判断,然后调用 new GetUniqueInstance()了。

所以问题就出来了,因为有两个线程,所以会创建两个实例,这便违反了单例模式的初衷,使得单例模式在多线程中出现不安全的问题。

这个问题我们可以通过线程锁机制对单例模式做相应的优化,即先将一个线程锁定,然后等这个线程完成以后,再让其他的线程访问GetUniqueInstance()中的 if 段语句。

双重校验锁形式单例模式核心代码:

 1 package com.wxb.singleton;
2
3 public class Singleton_Lazy_Safe {
4 /* --创建私有静态的自身实例对象-- */
5 private static Singleton_Lazy_Safe uniqueInstance = null;
6
7 /* --私有的构造方法,避免外界利用构造方法创建多个实例-- */
8 private Singleton_Lazy_Safe() {
9
10 }
11
12 /* --获取静态实例的方法--
13 * --该方法是静态的,可以通过类名直接调用--
14 */
15 public static Singleton_Lazy_Safe getUniqueInstance() {
16 /* --双重校验锁-- */
17 if (null == uniqueInstance) {
18 synchronized (Singleton_Lazy_Safe.class) {
19 if (null == uniqueInstance) {
20 uniqueInstance = new Singleton_Lazy_Safe();
21 }
22 }
23 }
24 return uniqueInstance;
25 }
26 }

关于使用双重校验的原因:

如果有两个线程同时到达,即同时调用了GetUniqueInstance(),此时由于 uniqueInstance == null ,所以两个线程都可以通过第一重的 singleton == null 校验,
进入第一重 if 语句后,由于存在锁机制,所以会有一个线程进入 lock 语句并进入第二重 uniqueInstance == null ,而另外的一个线程则会在 synchronized 语句的外面等待。

当第一个线程执行完 new Singleton_Lazy_Safe()语句后,便会退出锁定区域,此时,第二个线程便可以进入synchronized语句块,此时,如果没有第二重 uniqueInstance == null 的话,那么第二个线程还会继续调用 new Singleton_Lazy_Safe()语句,这样第二个线程又会创建一个 Singleton 实例,违反了“唯一实例”。

由于饿汉式单例类类被加载的时候,就会自行初始化uniqueInstance这个静态的自身实例对象。而不是在第一次调用GetUniqueInstance()时再来实例化单例类的唯一实例,所以饿汉式单例不需要编写多线程安全代码。

java基础之设计模式之单例模式的更多相关文章

  1. 第二十七节:Java基础面向对象-静态,单例模式,继承详情知识点

    前言 Java基础面向对象-静态,单例模式,继承详情知识点.静态-static关键字,static变量,静态代码块,代码块(不加静态),对象创建过程,单例模式,继承. 静态-static关键字 // ...

  2. java 23 - 2 设计模式之单例模式

    单例模式:保证类在内存中只有一个对象. 如何保证类在内存中只有一个对象呢?  A:把构造方法私有  B:在成员位置自己创建一个对象  C:通过一个公共的方法提供访问 单例模式之饿汉式: (一进来就造对 ...

  3. Java基础-单列设计模式

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

  4. Java进阶篇设计模式之一 ----- 单例模式

    前言 在刚学编程没多久就听说过设计模式的大名,不过由于当时还是个彻彻底底的菜鸟,并没有去触碰.直到在开始工作中对简单的业务代码较为熟悉之后,才正式的接触设计模式.当时最早接触的设计模式是工厂模式,不过 ...

  5. Java中的设计模式之单例模式

    Java中的单例模式 设计模式是软件开发过程中经验的积累 一.单例模式 1.单例模式是一种常用的软件设计模式,通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控 ...

  6. Java基础-工厂设计模式(三锅的肥鸡)

    ---恢复内容开始---   1)还没有工厂时代:假如还没有工业革命,如果一个你要一架飞机,一般的做法是自己去建造一架飞机,然后拿来开 通常的结果就是 有些时候 要么专科螺钉 没打好  要么就是 那个 ...

  7. JAVA基础—适配器设计模式

    适配器概念 在计算机编程中,适配器模式将一个类的接口适配成用户所期待的.使用适配器,可以使接口不兼容而无法在一起工作的类协调工作,做法是将类自己包裹在一个已经存在的类中. JDK对适配器设计模式的应用 ...

  8. [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html   谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...

  9. 【Java基础】Java设计模式简介

    什么是设计模式 设计模式(Design pattern)是一套被反复使用.被多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性.设计 ...

随机推荐

  1. Vue-cli3.0配置全局less

    第一种配置方式(推荐) npm install style-resources-loader vue-cli-plugin-style-resources-loader less-loader les ...

  2. 关于java的Excel导入导出之easypoi

    导入easypoi相关jar包,这里的easypoi-base的包也可以不倒入,因为easypoi-web中有依赖easypoi-base会自动导入的 <!-- https://mvnrepos ...

  3. shell 之 循环执行某操作

    需求: 按月执行201904到202010的py脚本. 代码如下: #!/bin/bash i=201904 # 定义开始月份 while [ $i -le 202010 ] # 当i小于等于2020 ...

  4. 长安“战疫”网络安全卫士守护赛writeup

    一. 解题情况 二. 解题过程 题目一 八卦迷宫 用画图工具手工连接,然后将路上的图表和字相对应 按顺序打出,然后根据题目要求换成全拼,加上图片里的前缀cazy{}提交 flag为: cazy{zha ...

  5. 深入理解Java虚拟机之自己编译JDK

    题外话 最近在阅读<深入理解Java虚拟机>,其中有一小节实战是自己编译JDK,实际操作下来后遇到问题不少,为此特地记录,也希望可以给大家带来一些参考! 前置准备 平台及工具:Window ...

  6. 18张图,详解SpringBoot解析yml全流程

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 前几天的时候,项目里有一个需求,需要一个开关控制代码中是否执行一段逻辑,于是理所当然的在yml文件中配置了一个属性作为开关,再配合nacos就可 ...

  7. java基础04-数据类型扩展及面试题

    java基础04-数据类型扩展及面试题讲解 public class demo02 { public static void main(String[] args){ // 一.整数拓展: 进制 二进 ...

  8. java 报错: MalformedURLException: unknow protocol: f

    问题: java 使用 URL 读取文件解读报错 MalformedURLException 1.使用 URL对象解析文件报错MalformedURLException: unknow protoco ...

  9. 今天太开心了,因为我知道了seastar框架

    今天听说了一个新的C++语言开发的网络框架,叫做seastar. seastar有何特别之处呢?先看看官网提供的性能数据: 性能 HTTPD benchmark: cpu # request/sec ...

  10. 2022年最新黑苹果monterey安装efi分享

    最新版本monterey 12.1 安装. 配置: 名称 型号 备注 主板 Gigabyte Z490M Gaming X   内存 威刚万紫千红DDR4 2666 16G x 2 两条16G  插2 ...