Java设计模式-单例模式

2023-11-07

JAVA设计模式课堂整理(代码都是maven引入junit包)
pom文件:

 <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
    </dependencies>


单例模式属于设计模式中的创建型模式,研究的是对象创建问题

单例模式

单例模式是确保某─个类只有一个实例,而且自行实例化并向整个系统提供这个实例,
注意:某个类只能有一个实例,类必须自行创建这个实例,以公共、统一的方式向整个系统提供这个实例。

饿汉式单例模式:

线程安全,调用时间效率较高,不支持延迟加载
Java类:

package org.tawil.demo.singleton_pattern.hungry;
//1/本类一旦初始化(静态属性随类初始化赋初值),对象即被创建,是立即加载(饿汉式)
public class HungrySingleton{
   public static void fn(){

   }
    //2.定义一个私有的本类型的静态属性,并直接创建本类对象赋值,而且仅能在类的初始化时赋值一次

    private static HungrySingleton instance = new HungrySingleton () ;
//3.提供公有的静态的获取对象实例的方法
public static HungrySingleton getInstance () {
    return instance;
}


//1.构造方法私有化
private HungrySingleton(){
    System.out.println("hungrysingleton is be ready");
  }
}

测试类

import org.junit.Test;
import org.tawil.demo.singleton_pattern.hungry.HungrySingleton;
public class singleton_patternTest {

    //测试饥汉式
    @Test
    public void hungryTest(){
        HungrySingleton.fn ( );// Hungrysingleton第一次被使用
        System.out.println( "-----------------------------------") ;

        HungrySingleton instance1= HungrySingleton.getInstance() ;
        HungrySingleton instance2 = HungrySingleton.getInstance() ;

        System.out.println(instance1 == instance2);

        }
      }

在这里插入图片描述

懒汉式单例模式:

线程安全(显示使用同步机制),调用时间效率较低,支持延迟加载

Java类:

package org.tawil.demo.singleton_pattern.lazy;

public class LazySingleton {
    public static void fn (){}

    //此处不赋初始值
    private static LazySingleton instance;
    public static LazySingleton getInstance() {
        synchronized (LazySingleton.class) {
            if (instance == null) {
//如果没有引入同步机制,当一个线程运行到这儿的时候,另一个线程可能刚好在执行if(instance == null)
// 结果两个线程都进入了本if分支
                instance = new LazySingleton();
            }
            return instance;
        }
    }

private  LazySingleton() {
            System.out.println("lazysingleton is be ready! ");
        }
    }





测试类:

import org.junit.Test;
import org.tawil.demo.singleton_pattern.lazy.LazySingleton;

public class singleton_patternTest {
//测试懒汉式
    @Test
    public void lazyTest(){
        LazySingleton.fn ( );// Hungrysingleton第一次被使用
        System.out.println( "-----------------------------------") ;

        LazySingleton instance1=  LazySingleton.getInstance() ;
        LazySingleton instance2 =  LazySingleton.getInstance() ;

        System.out.println(instance1 == instance2);

    }

    //测试懒汉式多线程
    @Test
    public void lazysTest() throws InterruptedException {
    Thread t1 = new Thread(){
        @Override
        public void run(){
            LazySingleton.getInstance();
        }
    };

    Thread t2 = new Thread(){
        @Override
        public void run(){
            LazySingleton.getInstance();
            }
        };


    t1.start();
    t2.start();

    t1.join();//测试线程等待t1线程结束,再继续进行t2-join ();
    t2.join();//测试线程等待t2线程结束,再继续进行
//注: junit测试线程结束时,会调用system.exit(0),导致整个系统终止


    }
}

在这里插入图片描述

懒汉式单例模式升级–双检锁单例模式:

在懒汉式中:

 //此处不赋初始值
    private static LazySingleton instance;
    public static LazySingleton getInstance() {
        synchronized (LazySingleton.class) {
            if (instance == null) {
//如果没有引入同步机制,当一个线程运行到这儿的时候,另一个线程可能刚好在执行if(instance == null)
// 结果两个线程都进入了本if分支
                instance = new LazySingleton();
            }
            return instance;
        }

如果interest为null,仍会进入此同步锁,等待同步锁,会降低效率
因此在这个外部再加一个检测锁:

 if (instance == null) {}

此时如果interest不为null,不会进入此同步锁,不会等待同步锁,不会降低效率
instance = new DoubleCheckSingleton();执行步骤
1.在堆中分配空间(只要分配空间,引用即实际存在)
2.对象初始化
3.将对象的引用赋给变量instance

        但有些编译器为提高效率会进行指令重排,将2,3颠倒。
        此时:有可能某个线程被引用结果对象初始化未完成运行错误。
        因此要避免指令重排
        **使用volatile修饰变量**,禁止指令重排
        Java类:
package org.tawil.demo.singleton_pattern.DoubleCheckSingleton;
//双检索式
public class DoubleCheckSingleton {
    public static void fn (){}
    //此处不赋初始值
    //此处使用volatile修饰变量
    private static volatile DoubleCheckSingleton instance;
    public static DoubleCheckSingleton getInstance() {
        if (instance == null) {//第一重检测锁锁
            
            synchronized (DoubleCheckSingleton.class) {
                if (instance == null) {//第二重检测锁
                    instance = new DoubleCheckSingleton();
               }
            }
         }
            return instance;
        }

    private  DoubleCheckSingleton() {
        System.out.println("DoubleCheckSingleton is be ready! ");
    }
}

测试类类似懒汉式:

 //测试双检锁式
        @Test
        public void DoubleCheckSingletonTest(){
            DoubleCheckSingleton.fn ( );// Hungrysingleton第一次被使用
            System.out.println( "-----------------------------------") ;

            DoubleCheckSingleton instance1=  DoubleCheckSingleton.getInstance() ;
            DoubleCheckSingleton instance2 =  DoubleCheckSingleton.getInstance() ;

            System.out.println(instance1 == instance2);

        }

静态内部类方式的单例模式:

线程安全,调用时间效率较高,支持延迟加载双重检测锁式单例模式:线程安全、调用时间效率较高,支持延迟加载
Java类

package org.tawil.demo.singleton_pattern.StaticInnerSingleton;

public class StaticInnerSingleton {
    public static void fn (){}

    private static class Inner{
        private static StaticInnerSingleton instance = new StaticInnerSingleton();
    }

    public static StaticInnerSingleton getInstance(){
        return Inner.instance;
    }

    private StaticInnerSingleton(){
        System.out.println("StaticInnerSingleton is be ready!");
    };
}

测试类:

//测试静态内部锁式
    @Test
    public void StaticInnerSingletonTest(){
        StaticInnerSingleton.fn ( );// Hungrysingleton第一次被使用
        System.out.println( "-----------------------------------") ;

        StaticInnerSingleton instance1=  StaticInnerSingleton.getInstance() ;
        StaticInnerSingleton instance2 =  StaticInnerSingleton.getInstance() ;

        System.out.println(instance1 == instance2);

    }


枚举方式的单例模式:

线程安全、调用时间效率较高,立即加载

Java类:

package org.tawil.demo.singleton_pattern.Enum;

public enum EnumSingleton {
    instance;//枚举常量,天然单例,立即加载(类似饿汉式)

    private EnumSingleton(){
        System.out.println("枚举式单例对象创建了!");
    }
    public static void fn(){}
    public void func(){
        System.out.println("func================>");
    }
}



测试类:

@Test
    public void 测试枚举式单例模式(){

        EnumSingleton.fn();
        System.out.println("-------------------------------");

        System.out.println(EnumSingleton.instance == EnumSingleton.instance);
        EnumSingleton.instance.func();

    }

在这里插入图片描述

总结

单例模式 特点
饿汉式 线程安全,调用时间效率较高,不支持延迟加载
懒汉式 线程安全(显示使用同步机制),调用时间效率较低,支持延迟加载
静态内部类 线程安全,调用时间效率较高,支持延迟加载
双重检测锁式 线程安全、调用时间效率较高,支持延迟加载
枚举式 线程安全、调用时间效率较高,立即加载
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java设计模式-单例模式 的相关文章

  • Java EE 6 和单例

    谁能解释一下在 Java EE 6 应用程序中实现 Singleton 的完整过程 我假设我不应该以声明静态变量的典型方式创建单例 而应该使用 Singleton注解 我必须这样做吗 难道只是声明一下的情况 Singleton就是这样 我还
  • 我在使用 JavaFX 绘制十字时遇到问题

    我正在尝试编写代码 在网格上对角绘制 3 个形状 前两个形状是正方形和圆形 我能做到 然而 第三种形状让我有些悲伤 我应该画一个十字 T 版本 而不是 X 每次我写出代码时 它看起来就像一个侧面 我知道我只是错过了一些简单的东西 但我真的很
  • UcanaccessSQLException:UCAExc:::3.0.1 表达式的数据类型不是布尔值

    我有一张如下图所示的表格 我需要获取其库尔德语单词包含的所有英语单词 r 所以我不能使用 select English from Table1 where Kurdish like 因为它还接受另一个单词中的子字符串 例如 当我尝试在查询中
  • Spring安全+LocaleResolver

    我需要在身份验证成功后更改区域设置 区域设置解析器
  • Hibernate 每个子类一个表继承策略的效率

    我正在考虑 Hibernate 管理的类层次结构的表布局 当然 每个子类表技术在我看来是一般意义上最合适的 然而 通过逻辑思考 我对其性能有些担忧 尤其是随着子类数量的扩展 举一个非常简短 且经典 的示例 假设您有以下类 public ab
  • 使用 JavaScript 与 Web 服务器通信的 Applet 是否可以迁移到 JWS?

    只是分享一些信息 希望对社区有用 由于各种浏览器停止支持插件 Applet 的可用性已经下降 Google 已决定停止对 NPAPI 插件的支持 EDGE 不支持插件 Firefox 也不鼓励使用插件 Mozilla 可能会跟进该套件 我们
  • Java:while循环冻结程序

    我正在制作一个游戏 我需要每 3 秒更新一次 JProgressBar 为此 我使用 while 循环 问题是我的程序由于 while 循环而冻结 我在其他问题中读到它 他们没有帮助我解决这个问题 我不知道如何解决 这是我的代码 publi
  • Grails 项目 - Servlet 调用 - ClassNotFoundException:javax.servlet.AsyncContext

    我在用 IntelliJ IDEA 终极版 12 4 grails 2 2 0 BuildConfig groovy 文件中的 grails servlet version 2 5 并实现了简单的 servlet post 请求 使用 RE
  • AMQP Spring 集成错误处理

    我的集成流程如下所示 Bean public IntegrationFlow auditFlow Qualifier eventLoggingConnectionFactory ConnectionFactory connectionFac
  • 如何将日期字符串解析为Date? [复制]

    这个问题在这里已经有答案了 如何将下面的日期字符串解析为Date object String target Thu Sep 28 20 29 30 JST 2000 DateFormat df new SimpleDateFormat E
  • 为什么当达到 InitiatingHeapOccupancyPercent 时 G1 不开始标记周期?

    根据文档 http www oracle com technetwork articles java g1gc 1984535 html XX InitiatingHeapOccupancyPercent 设置触发标记周期的Java堆占用阈
  • SSLContext 初始化

    我正在看JSSE参考指南 我需要获取一个实例SSLContext为了创建一个SSLEngine 所以我可以使用它Netty以启用安全性 获取实例SSLContext I use SSLContext getInstance 我看到该方法被重
  • 我可以使用 Selenium Webdriver 测试元素的顺序吗?

    有一个表单 其中有 3 个字段 具有 3 个不同的 ID fieldset div div fieldset
  • 在 Apache Servicemix 4 中的 OSGi 包之间共享配置文件?

    有人能够在 SMX4 中的两个或多个捆绑包之间成功共享配置吗 我正在寻找的是这样的 有一个文件 SMX HOME etc myconfiguration cfg 使此配置 可用 以便使用 Spring dm 通过 OSGi 配置管理将其注入
  • Java DNSLookup MX 记录列表。类似于 MXToolBox

    我正在构建一个程序来列出域的所有 MX 记录 起初似乎工作正常 但与在线工具进行比较后http mxtoolbox com http mxtoolbox com 有些域程序无法获取 MX 记录 而 MXToolbox 可以 我不确定原因是什
  • 短 2 个字节

    我正在从串行端口读取一个长度为 133 字节的数据包 最后 2 个字节包含 CRC 值 我使用 Java 将 2 个字节值制成单个 我认为很短 这就是我所做的 short high 48 0x00ff short low 80 short
  • 按钮悬停和按下效果 CSS Javafx

    我是 CSS 新手 为按钮定义了以下 CSS 样式 其中id并且应用了自定义样式 但不应用悬停和按下效果 bevel grey fx background color linear gradient f2f2f2 d6d6d6 linear
  • 空检查时可能未初始化错误

    我正在检查变量是否已初始化 但此时 netbeans 给了我variable reader might not have been initialized警告 我该如何解决 抑制这个问题 这是我的代码 摘要 final Reader rea
  • 将 SQL 数据中的一行映射到 Java 对象

    我有一个 Java 类 其实例字段 以及匹配的 setter 方法 与 SQL 数据库表的列名相匹配 我想优雅地从表中获取一行 到 ResultSet 中 并将其映射到此类的实例 例如 我有一个 Student 类 其中包含实例字段 FNA
  • 需要在没有wsdl的情况下调用soap ws

    我是网络服务的新手 这个网络服务是由 siebel 提供的 我需要调用一项网络服务 我的客户向我提供了以下详细信息 这是 SOAP 对于产品 请使用它作为端点 Request

随机推荐

  • Redis之String类型

    文章目录 Redis之String类型 1 赋值 获取值 2 同时设置 获取多个键值 3 数值增减 4 获取字符串长度 5 向尾部追加值 6 分布式锁 7 应用场景 Redis之String类型 Redis命令不区分大小写 1 赋值 获取值
  • 测试基础-系统测试包括哪些内容

    一 系统测试包含哪些测试 1 测试范围 整个系统 功能 性能 安全 界面 兼容等等 2 测试方法 黑盒测试 3 测试依据 需求规格说明书 SRS 4 评估基准 需求覆盖 5 测试类型 测试策略 补充说明 实例 淘宝登录操作 10万用户操作
  • 腾讯架构师谈技术管理:十年沉浮,最后我选择了离开……

    转自 http www techug com post tencent architect talk about team managment html 作者介绍 韩伟 腾讯科技互娱研发部架构师 曾在网易任职8年 担任无线事业部产品总监 多
  • lwip协议栈创建web服务器,基于LWIP的WEB服务器的研究与实现

    摘要 随着嵌入式系统的蓬勃发展 嵌入式技术已经被用于家庭 工业设备 军事等各个领域 同时Internet技术的日趋成熟 让各种嵌入式设备共享互联网的资源 将信息快速的传递到世界的另一端变得越来越紧迫 因此将嵌入式设备与Internet技术的
  • 单变量线性回归实现波士顿房价预测

    1 预测过程 1 波士顿地区房价数据获取 数据来自于sklearn自带数据集 2 波士顿地区房价数据分割 3 训练与测试数据标准化处理 4 使用最简单的线性回归模型LinearRegression对房价进行预测 2 回归算法的评价指标有MS
  • python基础教程:Python基于递归算法实现的走迷宫问题

    本文来源于公众号 csdn2299 喜欢可以关注公众号 程序员学府 本文实例讲述了Python基于递归算法实现的走迷宫问题 分享给大家供大家参考 具体如下 什么是递归 简单地理解就是函数调用自身的过程就称之为递归 什么时候用到递归 如果一个
  • 以太网帧、IP数据报的图解格式(包含相关例题讲解,一题足够)

    目录 一 基础知识 1 1 UDP段 IP数据报 以太网帧图示 1 2 以太网帧图示 1 3 IP数据报图示 二 例题讲解 1 1 题目及答案 1 2 答案解析 一 基础知识 1 1 UDP段 IP数据报 以太网帧图示 通信过程中 每层协议
  • git ssh key生成

    01 什么是Github和Git GitHub是一个面向开源及私有软件项目的托管平台 因为只支持git 作为唯一的版本库格式进行托管 故名GitHub 我们可以在github上建立一个网上的仓库 可以把代码提交到网上 让别人也可以看到我们的
  • KeyError: Spider not found 5种出错的情况

    KeyError Spider not found name一样 为何还是找不到spider 呢 往下看看 总有一个是你要的答案 第一种 最简单的错误 运行的爬虫名字与爬虫文件中的name不相同 解决方案 令两者名字相同即可 当然90 的人
  • 【React】中渲染列表、添加点击事件

    渲染列表 例如有如下数组 11 22 33 在react中可以用数组的map方法 import React Component from react export default class App extends Component co
  • 购物单

    题目如下 小明刚刚找到工作 老板人很好 只是老板夫人很爱购物 老板忙的时候经常让小明帮忙到商场代为购物 小明很厌烦 但又不好推辞 这不 XX大促销又来了 老板夫人开出了长长的购物单 都是有打折优惠的 小明也有个怪癖 不到万不得已 从不刷卡
  • linux报错:cannot create temp file for here-document: No space left on device

    文章目录 1 问题描述 2 问题定位 3 解决方案 1 问题描述 linux系统中使用cd命令进入某目录时 像往日一样利用tab键进行文件名的补全 结果报如下错误 cannot create temp file for here docum
  • 服务器接硬盘的那个叫什么名字,服务器硬盘接口和普通硬盘接口区别是什么?...

    服务器英文名称为Server 是计算机的一种 是网络中为客户端计算机提供各种服务的高性能的计算机 那么本篇就说说服务器硬盘接口和普通硬盘接口的区别 服务器硬盘接口包括SATA接口 SCSI接口 SAS接口 光纤接口4种 由于固态硬盘价格贵
  • Zxing和QR CODE 生成与解析二维码实例(普通篇)

    首先下载对应的jar包 本实例用的是Zxing2 2jar 下载地址 http download csdn net detail gao36951 8161861 Zxing是Google提供的关于条码 一维码 二维码 的解析工具 提供了二
  • Linux查找文件和目录,重定向输出 ,系统默认运行级别的查看和设置理论和练习

    作者 小刘在C站 个人主页 小刘主页 每天分享云计算网络运维课堂笔记 努力不一定有回报 但一定会有收获加油 一起努力 共赴美好人生 夕阳下 是最美的绽放 树高千尺 落叶归根人生不易 人间真情 目录 一 Linux 二 查找文件和目录 1 查
  • Windows Server 2012 R2 -webDAV管理(VMware workstation环境)

    安装URL及webDAV组件 启动设置webDAV 身份验证 客户端设置 连接测试
  • DNS缓存病毒防护43.227.220

    DNS缓存病毒又称DNS欺骗 是一种通过查找并利用DNS系统中存在的漏洞 将流量从合法服务器引导至虚假服务器上的攻击方式 在实际的DNS解析过程中 用户请求某个网站 浏览器首先会查找本机中的DNS缓存 如果DNS缓存中记录了该网站和IP的映
  • Onetab快速删除所有历史网页

    1 打开网页的控制台 F12 2 控制台粘贴该命令 document querySelectorAll div deleteAllButton forEach function ele index list ele click 3 然后按住
  • 我的CSDN三周年创作纪念日

    机缘 和老王研究读取和处理FY 4A AGRI数据 研究怎么生成经纬度查找图像 怎么处理 后来有了结果 就想着要不发到CSDN上 分享给大家 也能收获几个粉丝 收获 这个过程更多的是一种收获感和幸福感吧 收获了18w 的阅读和400多个粉丝
  • Java设计模式-单例模式

    JAVA设计模式课堂整理 代码都是maven引入junit包 pom文件