【设计模式-2.1】创建型——单例模式

说明:设计模式根据用途分为创建型、结构性和行为型。创建型模式主要用于描述如何创建对象,本文介绍创建型中的单例模式。

饿汉式单例

单例模式是比较常见的一种设计模式,旨在确保对象的唯一性,什么时候去使用这个对象都是同一个。这样设计的目的是为了避免对象重复创建,浪费资源,同时也保证了对象的唯一性,不至于多个相同的对象,状态不一致的情况。

以下是单例模式的简单实现:

/*** 太阳类*/
public class Sun {private static final Sun sun = new Sun();private Sun() {}public static Sun getInstance() {return sun;}
}

需要注意,对象的创建是在对象类内部,且为static final修饰,并且私有化构造方法,使其不能在外部被创建,其次创建一个静态方法,返回其对象

此时,外部通过类名.方法名的方式,可以访问到该对象,且始终为同一个;

public class Test {public static void main(String[] args) {Sun sun1 = Sun.getInstance();Sun sun2 = Sun.getInstance();System.out.println(sun1 == sun2);}
}

两次获取到的对象相同

在这里插入图片描述

上面这种创建方式,称为饿汉式单例(Eager Singleton),即类加载完成时就创建对象

懒汉式单例

以下这种方式,称为懒汉式单例(Lazy Singleton),在调用静态方法时才创建对象

/*** 懒汉式单例模式*/
public class LazySun {private static LazySun sun = null;private LazySun() {}public static LazySun getInstance() {if (sun == null) {sun = new LazySun();}return sun;}
}

这种创建方式,可以实现延迟加载,节约资源。但是在多线程并发时,如果有多个线程在if (sun == null),就会导致对象被创建多次,所以我们很容易想到的是加锁,将静态方法加上锁,如下:

/*** 懒汉式单例模式*/
public class LazySun {private static LazySun sun = null;private LazySun() {}public synchronized static LazySun getInstance() {if (sun == null) {sun = new LazySun();}return sun;}
}

但是,给方法加上锁后,会影响性能,可以考虑减少锁的范围,只锁住创建对象这一行,如下:

/*** 懒汉式单例模式*/
public class LazySun {private static LazySun sun = null;private LazySun() {}public static LazySun getInstance() {if (sun == null) {synchronized (LazySun.class) {sun = new LazySun();}}return sun;}
}

双重检查锁定

但是,还有问题。在多线程并发下,如果线程A在创建对象(未完成),线程B、C在if (sun == null) 这里判断为true,即便对象创建完成,线程B、C通过了if判断,也还是会依次再创建对象,也造成了对象被重复创建。因此,还需要改造,如下:

/*** 双重检查锁定*/
public class LazySun {private volatile static LazySun sun = null;private LazySun() {}public static LazySun getInstance() {// 第一次判断if (sun == null) {synchronized (LazySun.class) {// 第二次判断if (sun == null){sun = new LazySun();}}}return sun;}
}

就是在锁住的代码块里面再进行一次非空判断,称为双重检查锁定(Double-Check Locking),同时,单例对象修饰符加上volatile,确保多个线程都能正确处理;

IoDH

饿汉式单例,是在类被加载时就创建了对象。不需要考虑多线程,但是无论是否使用到对象都创建,造成了资源浪费。而懒汉式单例,虽然做到了延迟加载,但是需要处理好多线程情况下的对象创建,使用了锁,影响了性能。

那有没有一种更好了方式,既能在多线程下使用,又不会影响性能?

在《设计模式的艺术》(刘伟著)中作者提供了一种更好的创建方式,称为IoDH(Initialization on Demand Holder,按需初始化),代码如下:

/*** IoDH*/
public class Singleton {private Singleton() {}private static class HolderClass {private final static Singleton instance = new Singleton();}public static Singleton getInstance() {return HolderClass.instance;}
}

这种方式是对饿汉式单例的改进,是在单例类里创建了一个内部类,将单例对象的创建放在了这个内部类里面。因为单例对象不是单例类的一个成员变量,所以对象在类加载时不会被创建,而是会在调用静态方法时被创建,这样既能延迟加载,又没有使用锁,影响性能,一举两得。

书中说,通过使用IoDH,既可以实现延迟加载,又可以保证线程安全,不影响系统性能。因此,IoDH不失为一种最好的Java语言单例模式实现方式;其缺点是与编程语言本身的特性相关,很多面向对象语言不支持IoDH。

总结

本文参考《设计模式的艺术》、《秒懂设计模式》两书

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/169703.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 批量插入记录报 Error 1390 (HY000)

文章目录 1.背景2.问题3.分批插入4.一次最多能插入多少条记录?参考文献 1.背景 Golang 后台服务使用 GORM 实现与 MySQL 的交互,在实现一个通过 Excel 导入数据的接口时,使用 Save 方法一次性插入大量记录(>1w)时报…

springsecurity6配置四

一、springsecurity自定义过滤url配置 package com.school.information.config;import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component;import java.util.List;/*** 需要放行的…

LiveGBS流媒体平台GB/T28181功能-查看国标设备会话列表直播会话、回放会话、下载会话、对讲会话

LiveGBS流媒体平台GB/T28181功能-查看国标设备会话列表直播会话、回放会话、下载会话、对讲会话 1、会话列表2、会话类型3、搭建GB28181视频直播平台 1、会话列表 LiveGBS-> 国标设备-》点击在线状态 点击会话列表 2、会话类型 下拉会话类型可以看到 直播会话、回放会话、…

不用排队升级GPT/获取api

想要在国内获取api key,可以使用这种方法 小技巧:目前GPT还是排队订阅,可以直接用链接:https://chat.openai.com/invite/accepted 即可跳过排队环节 接下来先看一下如何购买腾讯云服务器 第一步:打开腾讯云 腾讯云 …

Python爬虫知识储备

Python爬虫知识储备 一、基础知识 常见的Python爬虫相关库和工程化爬虫框架: 请求库: requests:用于发送HTTP请求并获取响应的流行库。它简单易用,适合大多数爬虫任务。urllib:Python的标准库之一,包含…

文件上传漏洞的理解

文件上传漏洞的理解 1. 漏洞描述: 文件上传漏洞是指攻击者可以利用Web应用程序中存在的缺陷,向服务器上传恶意文件,从而实施攻击或者获取敏感信息的安全漏洞 2. 漏洞原理: 文件上传漏洞通常是由于开发者在设计Web用于程序时未对上…

Visual Studio 2019 C# System.BadImageFormatException 解决方法

文章目录 1.DLL文件缺失或不匹配原因解决方法 2.系统环境变量Path下内容过多原因解决方法 3.位数错误原因解决方法 分析几种可能因素 1.DLL文件缺失或不匹配 原因 检查对应Debug路径下的DLL文件是否有缺失 解决方法 将对应的DLL文件放到Debug文件夹里面,检查冗余…

用结构体实现时间换算

【问题描述】用结构体类型表示时间内容&#xff08;时间以时分秒表示&#xff09;输入一个时间数据&#xff0c;在输入一个秒数n(n<60)&#xff0c;以h:m:s的形式输出过了n秒后的时间。&#xff08;超过24点以0点开始&#xff09; 【输入形式】输入的时间必须是以"时:分…

二进制搭建以太坊2.0节点-2023最新详细版文档

文章目录 一、配置 JWT 认证二、部署执行节点geth2.1 下载geth二进制文件2.2 geth节点启动三、部署共识节点Prysm3.1 下载Prysm脚本3.2 Prysm容器生成四、检查节点是否同步完成4.1 检查geth执行节点4.2 检查prysm共识节点4.3 geth常用命令五、节点同步详细说明5.1 启动时日志5.…

【nlp】3.4 Transformer论文复现:2. 编码器部分(规范化层、子层连接结构、编码器层)

3.4 Transformer论文复现:2. 编码器部分(规范化层、子层连接结构、编码器层) 2.6 规范化层2.6.1 规范化层的作用2.6.2 规范化层的代码实现2.6.3 规范化层总结2.7 子层连接结构2.7.1 子层连接结构2.7.2 子层连接结构的代码实现2.7.3 子层连接结构总结2.8 编码器层2.8.1 编码器…

抖音权重查询源码H5源码

源码下载&#xff1a;123网盘

Linux中安装MySQ-合集

Linux中安装MySQL Centos中 1、卸载不必要的软件 先卸载mariadb安装MySQL必要环境 rpm -qa|grep mariadb rpm -e --nodeps mariadb-libs yum install -y gcc-c yum install net-tools yum -y install gcc如果需要Java等程序 yum install -y java* java-1.8.0-openjdk* op…

2022年12月 Scratch(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 默认小猫角色和气球角色都是显示状态,小猫程序如下图所示,气球没有程序,点击绿旗,舞台上最终显示的效果是?( ) A:可能出现6个不同位置的小猫和6个小球 B:可能出现6个不同位…

CentOS7搭建smb服务器

安装smb sudo yum install samba samba-client samba-common配置smb vim /etc/samba/smb.conf [shared] path /path/to/shared/folder writable yes browsable yes guest ok yes valid users yourname添加smb用户 sudo useradd youname sudo smbpasswd -a youname然后会…

python 爬百度热搜并生成词云

1、爬取百度body存入txt def get_baidu_hot():url "https://top.baidu.com/board?tabrealtime"headers {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3&…

Python 前后端分离项目Vue部署应用

一、视图创建 from django.http import JsonResponse from django.shortcuts import render# Create your views here. from django.views import Viewclass IndexView(View):def get(self,request):# 前后端分离 &#xff08;前端JS代码渲染数据&#xff09;return JsonRespo…

24. Spring源码篇之占位符填充${}

简介 在spring中占位符用${}表示&#xff0c;他可以很好的实现将变动的数据与代码分离&#xff0c;这部分变化的数据就可以使用配置文件等诸多手段动态配置 spring中的占位符应用的非常广泛&#xff0c;比如Value注解 RequestMapping Feign等都支持${} spring为该功能定义了…

Jensen不等式

如果是正数&#xff0c;并且它们的和等于1&#xff0c;f是凸函数&#xff0c;那么&#xff1a; 也可表述为&#xff1a; 即x期望的凸函数值小于等于x凸函数值的期望

分享常用设计模式之单例模式(懒汉模式和饿汉模式)和几种关于设计模式的面试题

目录 1.单例模式 1.懒汉模式 2.饿汉模式 2.设计一个不能被继承的类 3.设计一个不能被继承但是可以在外部环境创建该类对象的类 4.设计一个可以被继承但不能在外部环境创建该类的对象的类 5.限制派生类对象不能拷贝也不能赋值 1.单例模式 设计一个不能在外部环境创建该类…

python通过继承、组合、委托组织类

1 python通过继承、组合、委托组织类 #概念描述1继承属性查找X.name2多态方法调用X.method&#xff0c;取决于X的类型3封装方法和运算符实现行为 通常来说&#xff0c;独特的运算使用独特的方法名称&#xff0c;不要依赖于调用标记。 python组织类结构的方式包括&#xff1a…