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设计模式-单例模式 的相关文章

  • 中断并标签,“标签 MyLabel 丢失”

    我有这样的代码 if condition1 break MyLabel while true some code here MyLabel if condition2 break more code here 我收到此错误 标签 MyLab
  • Java Swing 应用程序消息对话框帮助

    我正在开发 Java Swing 应用程序 我需要创建一个如图所示的对话框 我不知道这个的名字 我无法解释 所以我附上一张照片 请告诉我这叫什么以及如何在我的 GUI 应用程序中创建它 给猫剥皮的方法不止一种 public final cl
  • 有没有更简单的方法来分割/重建字符串?

    目前我正在使用String split 像这样 String tmp props get i getFullName split String name for int j 1 j lt tmp length j if j gt 1 nam
  • 仅使用公钥在 HD 钱包中生成以太坊地址 (bitcoinj/web3j)

    我尝试为使用 bitcoinj 库实现的 HD 钱包密钥生成以太坊地址 但我感到困惑 DeterministicSeed seed new DeterministicSeed some seed code here null 1409478
  • 如何在JavaFX中有效地滚动和缩放大图像?

    作为图像处理应用程序的一部分 我需要创建具有缩放 滚动和矢量叠加功能的简单查看器模块 图像相当大 40000x20000 这使得 ImageView 上的操作变慢 缓冲等 在 JavaFX 中处理巨大图像时 改善用户体验的最佳选项是什么 我
  • Java:while循环冻结程序

    我正在制作一个游戏 我需要每 3 秒更新一次 JProgressBar 为此 我使用 while 循环 问题是我的程序由于 while 循环而冻结 我在其他问题中读到它 他们没有帮助我解决这个问题 我不知道如何解决 这是我的代码 publi
  • 如何将完整的日期格式拆分为日期和时间?

    我有很多格式为我的示例所示的字符串 我必须解析它们 我正在尝试确定今天是哪根弦 我的问题是 时间快到了 我只需要比较那个日期 接下来我想检查时间是否在 after 和 before 的两个时间戳 HH mm ss 之间 但存在问题 日期几乎
  • Glassfish 4 - JDBC 领域

    Glassfish 4 中的密码加密算法和摘要算法有什么区别 因为Password加密算法不能为空 所以我使用了MD5 Encoding使用了Hex 摘要算法为空 因此默认为 SHA 256 但是 如果我使用 JAAS 制作一个简单的登录应
  • 在 json 中解析尾随字符

    我正在尝试检查 json 是否有效 并且我遇到了奇怪的行为 当我将一些字符附加到可解析的 json 时 jackson 和 gson 都会解析它 并且它们会忽略尾随字符 我想检查 json 是否严格有效 请帮忙 我尝试了几个标志mapper
  • 始终等待页面加载到 PageObjects 上

    因此 当出现问题时 我只是创建了一个简单的 selenium JBehave 代码 我将首先发布简化的代码 然后稍后解释我的问题是什么 所以这里我们有一个简单的 AbstractClass 它将在我的 PageObjects 上继承 此类仅
  • org.openqa.selenium.NoSuchSessionException:会话 ID 为空。调用 quit() 后使用 WebDriver?

    我已经进行了一些搜索 但仍然遇到同样的问题 我相信这可能是由于我的网络驱动程序是静态的造成的 我不太确定 在我的主课中 我包括了 BeforeTest and AfterTest BeforeTest包括根据我的 XML 文件启动新浏览器
  • NIO 直接缓冲区何时以及如何被释放?

    我有一个 C 库 需要一个临时缓冲区作为暂存空间 我正在考虑将直接字节缓冲区的地址传递给它 在最终释放缓冲区之前 是否允许虚拟机重新定位缓冲区 JNI 框架消失后 本机库将保留该指针 我的理解是 JNI 本地对象引用无法缓存 因为 VM 可
  • Java 客户端到服务器未知来源

    我有一个简单的乒乓球游戏 需要通过网络工作 服务器将创建一个带有球和 2 个球棒位置的游戏 当客户端连接到服务器时 服务器将创建一个名为 PongPlayerThread 的新类 它将处理客户端到服务器的输入和输出流 我的服务器工作100
  • 如何在 QueryDSL 中选择文字

    我目前正在开发一个使用 queryDSL 和 hibernate 的项目 其中它需要一个选择文字 按照发布的示例here https stackoverflow com questions 18691317 querydsl how to
  • 自 JRE 1.7.0_25 起,Batik 无法进行转换

    自从我更新到 JAVA 1 7 0 25 以来 蜡染在应用转换时会抛出异常 堆栈跟踪是 java awt image ImagingOpException Unable to transform src image at java awt
  • 按钮悬停和按下效果 CSS Javafx

    我是 CSS 新手 为按钮定义了以下 CSS 样式 其中id并且应用了自定义样式 但不应用悬停和按下效果 bevel grey fx background color linear gradient f2f2f2 d6d6d6 linear
  • Eclipse 如何创建一个未解决编译问题的类?

    当我尝试使用 javac 编译此类时 出现编译错误并且未创建 Test class public class Test public static void main String args int x 1L lt this cannot
  • 如何在 Hibernate 中自动递增复合主键中的 Id?

    我有一个带有复合主键的表 groupId and batchId 实体类看起来像 Entity name EMPLOYEE public class Employee EmbeddedId private EmployeePK employ
  • 背景图像隐藏其他组件,例如按钮标签等,反之亦然

    如何解决此代码中组件的隐藏问题 代码运行没有错误 但背景图片不显示 如何更改代码以获取背景图像 使用验证方法时 它在validation 中创建错误 public class TEST public TEST String strm Jan
  • Volley 在第一次调用方法时返回 null

    我正在尝试使用 volley 从服务器检索数据 但是当我第一次调用此方法时 我收到服务器的响应 但该方法返回 null 如果我第二次调用它 我会得到最后的响应 public String retrieveDataFromServer Str

随机推荐

  • 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文件