02 Singleton单例

抽丝剥茧设计模式 之 Singleton单例 - 更多内容请见 目录

文章目录

  • 一、Singleton单例
  • 二、单例模式的八种实现
    • 1、饿汉式1
      • Java实现
      • go实现
    • 2、饿汉式2
      • Java实现
      • go实现
    • 3、懒汉式
      • Java实现
      • go实现
    • 4、懒汉式-加锁
      • Java实现
      • go实现
    • 5、懒汉式-缩小加锁代码块
      • Java实现
      • go实现
    • 6、懒汉式-双判断
      • Java实现
      • go实现
    • 7、静态内部类-同时保证线程安全和懒加载
      • Java实现
    • 8、枚举单例
      • Java实现
  • 总结


一、Singleton单例

Singleton单例常用于manager等只需要有一个实例的地方,但是由于正常情况我们无法阻止其他人创建实例,所以我们需要用Singleton单例模式来约束。
Singleton单例模式有8种写法,但是只有两种(7、8)完美无缺,但是完美的不常用。

二、单例模式的八种实现

1、饿汉式1

Java实现

/*** 饿汉式* 类加载到内存后,就实例化一个单例,JVM,保证线程安全,* 简单实用,推荐使用。* 唯一缺点,不管用到与否,类装载时就完成了实例化。*/public class Singleton {// 私有静态成员变量,直接创建实例private static final Singleton instance = new Singleton();// 私有构造方法,防止外部实例化private Singleton() { }// 公有静态方法,获取实例public static Singleton getInstance() {return instance;}}public class Main {public static void main(String[] args) {Singleton singleton = Singleton.getInstance();System.out.println(singleton.hashCode());Singleton anotherSingleton = Singleton.getInstance();System.out.println(anotherSingleton.hashCode());// 输出结果应为相同的hashCode,表示只有一个实例被创建}
}

go实现

package mainimport ("fmt""sync"
)// 饿汉式
type Singleton struct{}// 私有静态成员变量,直接创建实例
var instance *Singleton = &Singleton{}
var once sync.Once// 公有静态方法,获取实例
func GetInstance() *Singleton {return instance
}func main() {singleton := GetInstance()fmt.Println(singleton.hash())anotherSingleton := GetInstance()fmt.Println(anotherSingleton.hash())// 输出结果应为相同的hashCode,表示只有一个实例被创建
}func (s *Singleton) hash() int {return int(uintptr(unsafe.Pointer(s)))
}

2、饿汉式2

Java实现

/*** 饿汉式* 用静态语句块保证当getInstance()调用时才创建实例*/public class Singleton {// 私有静态成员变量,用静态语句块创建实例private static final Singleton instance;static {instance = new Singleton();}// 私有构造方法,防止外部实例化private Singleton() { }// 公有静态方法,获取实例public static Singleton getInstance() {return instance;}}public class Main {public static void main(String[] args) {Singleton singleton = Singleton.getInstance();System.out.println(singleton.hashCode());Singleton anotherSingleton = Singleton.getInstance();System.out.println(anotherSingleton.hashCode());// 输出结果应为相同的hashCode,表示只有一个实例被创建}
}

go实现

package mainimport ("fmt""sync"
)// 饿汉式
type Singleton struct{}// 私有静态成员变量,直接创建实例
var instance *Singleton
var once sync.Once// 公有静态方法,获取实例
func GetInstance() *Singleton {once.Do(func() {instance = &Singleton{}})return instance
}func main() {singleton := GetInstance()fmt.Println(singleton.hash())anotherSingleton := GetInstance()fmt.Println(anotherSingleton.hash())// 输出结果应为相同的hashCode,表示只有一个实例被创建
}func (s *Singleton) hash() int {return int(uintptr(unsafe.Pointer(s)))
}

3、懒汉式

Java实现

/*** 懒汉式* 虽然达到了按需初始化的目的,但却带来了线程不安全的问题。*/public class Singleton {// 私有静态成员变量private static Singleton instance;// 私有构造方法,防止外部实例化private Singleton() { }// 公有静态方法,获取实例public static /*synchronized*/ Singleton getInstance() {if (instance == null) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}instance = new Singleton();}return instance;}}public class Main {public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> {Singleton singleton = Singleton.getInstance();System.out.println(Thread.currentThread().getName() + " - " + singleton.hashCode());}).start();}}
}

go实现

package mainimport ("fmt""sync"
)// 懒汉式
type Singleton struct{}var instance *Singleton
var once sync.Once// 公有静态方法,获取实例
func GetInstance() *Singleton {if instance == nil {instance = &Singleton{}}return instance
}func main() {singleton := GetInstance()fmt.Println(singleton.hash())anotherSingleton := GetInstance()fmt.Println(anotherSingleton.hash())// 输出结果应为相同的hashCode,表示只有一个实例被创建wg := sync.WaitGroup{}for i := 0; i < 10; i++ {wg.Add(1)go func() {defer wg.Done()singleton := GetInstance()fmt.Println(singleton.hash())}()}wg.Wait()
}func (s *Singleton) hash() int {return int(uintptr(unsafe.Pointer(s)))
}

4、懒汉式-加锁

Java实现

/*** 懒汉式* 虽然达到了按需初始化的目的,但却带来了线程不安全的问题。*/public class Singleton {// 私有静态成员变量private static Singleton instance;// 私有构造方法,防止外部实例化private Singleton() { }// 公有静态方法,获取实例public static synchronized Singleton getInstance() {if (instance == null) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}instance = new Singleton();}return instance;}}public class Main {public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> {Singleton singleton = Singleton.getInstance();System.out.println(Thread.currentThread().getName() + " - " + singleton.hashCode());}).start();}}
}

go实现

package mainimport ("fmt""sync"
)// 懒汉式
type Singleton struct{}var instance *Singleton
var once sync.Once
var mu sync.Mutex// 公有静态方法,获取实例
func GetInstance() *Singleton {mu.Lock()defer mu.Unlock()if instance == nil {instance = &Singleton{}}return instance
}func main() {singleton := GetInstance()fmt.Println(singleton.hash())anotherSingleton := GetInstance()fmt.Println(anotherSingleton.hash())// 输出结果应为相同的hashCode,表示只有一个实例被创建wg := sync.WaitGroup{}for i := 0; i < 10; i++ {wg.Add(1)go func() {defer wg.Done()singleton := GetInstance()fmt.Println(singleton.hash())}()}wg.Wait()
}func (s *Singleton) hash() int {return int(uintptr(unsafe.Pointer(s)))
}

5、懒汉式-缩小加锁代码块

Java实现

/*** 懒汉式* 虽然达到了按需初始化的目的,但却带来了线程不安全的问题。*/public class Singleton {// 私有静态成员变量private static Singleton instance;// 私有构造方法,防止外部实例化private Singleton() { }// 公有静态方法,获取实例public static synchronized Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}instance = new Singleton();}}return instance;}
}public class Main {public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> {Singleton singleton = Singleton.getInstance();System.out.println(Thread.currentThread().getName() + " - " + singleton.hashCode());}).start();}}
}

go实现

package mainimport ("fmt""sync"
)// 懒汉式
type Singleton struct{}var instance *Singleton
var once sync.Once
var mu sync.Mutex// 公有静态方法,获取实例
func GetInstance() *Singleton {if instance == nil {mu.Lock()instance = &Singleton{}mu.Unlock()}return instance
}func main() {singleton := GetInstance()fmt.Println(singleton.hash())anotherSingleton := GetInstance()fmt.Println(anotherSingleton.hash())// 输出结果应为相同的hashCode,表示只有一个实例被创建wg := sync.WaitGroup{}for i := 0; i < 10; i++ {wg.Add(1)go func() {defer wg.Done()singleton := GetInstance()fmt.Println(singleton.hash())}()}wg.Wait()
}func (s *Singleton) hash() int {return int(uintptr(unsafe.Pointer(s)))
}

6、懒汉式-双判断

Java实现

/*** 懒汉式* 虽然达到了按需初始化的目的,但却带来了线程不安全的问题。*/public class Singleton {// 私有静态成员变量private static volatile Singleton instance;// 私有构造方法,防止外部实例化private Singleton() { }// 公有静态方法,获取实例public static synchronized Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {try {Thread.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}instance = new Singleton();}}}return instance;}
}public class Main {public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> {Singleton singleton = Singleton.getInstance();System.out.println(Thread.currentThread().getName() + " - " + singleton.hashCode());}).start();}}
}

go实现

package mainimport ("fmt""sync"
)// 懒汉式
type Singleton struct{}var instance *Singleton
var once sync.Once
var mu sync.Mutex// 公有静态方法,获取实例
func GetInstance() *Singleton {if instance == nil {mu.Lock()if instance == nil {instance = &Singleton{}}mu.Unlock()}return instance
}func main() {singleton := GetInstance()fmt.Println(singleton.hash())anotherSingleton := GetInstance()fmt.Println(anotherSingleton.hash())// 输出结果应为相同的hashCode,表示只有一个实例被创建wg := sync.WaitGroup{}for i := 0; i < 10; i++ {wg.Add(1)go func() {defer wg.Done()singleton := GetInstance()fmt.Println(singleton.hash())}()}wg.Wait()
}func (s *Singleton) hash() int {return int(uintptr(unsafe.Pointer(s)))
}

7、静态内部类-同时保证线程安全和懒加载

Java实现

/*** 靠JVM保证线程安全* 当外部类被加载时,内部类不会被加载* 当getInstance()被调用,SingletonHolder被加载* SingletonHolder是内部类,可以调用私有的构造器*/public class Singleton {// 私有构造方法,防止外部实例化private Singleton() { }private static class SingletonHolder {// 私有静态成员变量private final static Singleton instance = new Singleton();}public static Singleton getInstance() {return SingletonHolder.instance;}
}public class Main {public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> {Singleton singleton = Singleton.getInstance();System.out.println(Thread.currentThread().getName() + " - " + singleton.hashCode());}).start();}}
}

8、枚举单例

Java实现

/*** 枚举单例,不仅解决线程同步,还可以防止反序列化*/
public enum Singleton {instance;
}public class Main {public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> {System.out.println(Thread.currentThread().getName() + " - " + Singleton.instance.hashCode());}).start();}}
}

总结

老实用第一种就可以了。最后两种我没想好该怎么对应go的语法,容我想想。

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

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

相关文章

FastDFS之快速入门、上手

知识概念 分布式文件系统 通过计算机网络将各个物理存储资源连接起来。通过分布式文件系统&#xff0c;将网络上任意资源以逻辑上的树形结构展现&#xff0c;让用户访问网络上的共享文件更见简便。 文件存储的变迁&#xff1a; 直连存储&#xff1a;直接连接与存储&#xf…

websocket介绍并模拟股票数据推流

Websockt概念 Websockt是一种网络通信协议&#xff0c;允许客户端和服务器双向通信。最大的特点就是允许服务器主动推送数据给客户端&#xff0c;比如股票数据在客户端实时更新&#xff0c;就能利用websocket。 Websockt和http协议一样&#xff0c;并不是设置在linux内核中&a…

优化用户体验的设计原则和实用建议

在现代软件开发中&#xff0c;用户体验的质量直接关系到用户的满意度和产品的成功。通过采用良好的设计原则和实用建议&#xff0c;可以提升用户体验&#xff0c;使产品更具吸引力。本文将介绍一些优化用户体验的设计原则和实用建议。 1. 用户研究与理解 在设计之前深入了解目…

代码随想录算法训练营Day20 | 40.组合总和||、39.组合总和、131.分割回文串

LeetCode 40 组合总和|| 本题思路&#xff1a;由于解集中不能包含重复的组合&#xff0c;所以要进行去重的操作。 首先要将数组先进行一个排序操作然后在树层进行去重操作&#xff01;&#xff08;不懂的可以去看代码随想录讲解视频&#xff09;利用一个 used 数组来表示&…

全链路压力测试有哪些主要作用

全链路压力测试是在软件开发和维护过程中不可或缺的一环&#xff0c;尤其在复杂系统和高并发场景下显得尤为重要。下面将详细介绍全链路压力测试的主要作用。 一、全链路压力测试概述 全链路压力测试是指对软件系统的全部组件(包括前端、后端、数据库、网络、中间件等)在高负载…

解决 ubuntu 下编译文件的时候与 YAML 相关的的报错

输入&#xff1a; catkin build -DCMAKE_C_COMPILERgcc-8 -DCMAKE_CXX_COMPILERg-8 或 catkin build airsim_tutorial_pkgs -DCMAKE_C_COMPILERgcc-8 -DCMAKE_CXX_COMPILERg-8 报错如下&#xff1a; 可能是缺少 yaml-cpp 文件&#xff0c;然后操作&#xff1a; sudo apt-g…

书生·浦语大模型实战2

轻松玩转书生浦语大模型趣味 Demo 大模型及 InternLM 模型简介 什么是大模型 大模型通常指的是机器学习或人工智能领域中参数数量巨大、拥有庞大计算能力和参数规模的模型。这些模型利用大量数据进行训练&#xff0c;并且拥有数十亿甚至数千亿个参数。大模型的出现和发展得益…

单片机原理及应用——C51语言版(第2版,林立、张俊亮编著)课后习题及答案

第一章习题 1.1 单项选择题 &#xff08;1&#xff09; 单片机又称为单片微计算机&#xff0c;最初的英文缩写是____。 答案(D) A.MCPB.CPUC.DPJD.SCM &#xff08;2&#xff09; Intel公司的MCS-51系列单片机是______的单片机。 答案(C) A.1位B.4位C.8位D.16位 &#xf…

66.网游逆向分析与插件开发-角色数据的获取-角色类的数据分析与C++还原

内容来源于&#xff1a;易道云信息技术研究院VIP课 ReClass.NET工具下载&#xff0c;它下方链接里的 逆向工具.zip 里的reclass目录下&#xff1a;注意它分x64、x32版本&#xff0c;启动是用管理员权限启动否则附加时有些进程附加不上 链接&#xff1a;https://pan.baidu.com/…

【S32K 进阶之旅】 NXP S32K3 以太网 RMII 接口调试(2)

前言 前文介绍了 NXP S32K3 以太网 RMII 接口调试的开发环境搭建&#xff0c;下面开始详解软件调试步骤。没看过第一节的小伙伴请移步《【S32K 进阶之旅】 NXP S32K3 以太网 RMII 接口调试&#xff08;1&#xff09;》&#xff0c;话不多说我们直接进入正题。 lwip Stack 介绍 …

视频号小店发展趋势如何?适合新手吗?

我是电商珠珠 视频号团队在22年7月发展了自己的电商平台-视频号小店。截止到目前为止&#xff0c;也发展了不过一年的时间&#xff0c;所以各项平台政策还不太严谨。 一个新兴平台所做的第一步就是招揽更多的商家来入驻&#xff0c;就会将红利全部倾向商家&#xff0c;而在今…

Python 编写不同时间格式的函数

该代码是一个时间相关的功能模块&#xff0c;提供了一些获取当前时间的函数。 Report_time() 函数返回当前时间的格式化字符串&#xff0c;例如 "20240110114512"。Y_M_D_h_m_s_time() 函数返回当前时间的年、月、日、时、分、秒的元组格式。Y_M_D_h_m_s() 函数返回…

【笔记】书生·浦语大模型实战营——第三课(基于 InternLM 和 LangChain 搭建你的知识库)

【参考&#xff1a;tutorial/langchain at main InternLM/tutorial】 【参考&#xff1a;(3)基于 InternLM 和 LangChain 搭建你的知识库_哔哩哔哩_bilibili-【OpenMMLab】】 笔记 基础作业 这里需要等好几分钟才行 bug&#xff1a; 碰到pandas相关报错就卸载重装 输出文字…

PyTorch项目源码学习(2)——Tensor代码结构初步学习

PyTorch版本&#xff1a;1.10.0 Tensor Tensor是Pytorch项目较为重要的一部分&#xff0c;其中的主要功能如存储&#xff0c;运算由C和CUDA实现&#xff0c;本文主要从前端开始探索学习Tensor的代码结构。 结构探索 PyTorch前端位于torch目录下&#xff0c;从_tensor.py可以…

Python基础语法(上)——基本语法、顺序语句、判断语句、循环语句(有C++基础快速掌握Python语言)

文章目录 0.python小技巧与易错点1.python 与 c 语法有哪些区别2.Python基本语法2.1python的变量类型2.2python中的运算符2.3python中的表达式2.4python中的输入输出 3.python判断语句3.1基本用法&#xff1a;3.2关于else if 的用法3.3关于pass语句3.4python变量的作用域3.5pyt…

Java刷题错题笔记-day04-集合

1.在JDK8中&#xff0c;ConcurrentHashMap的数据结构是怎样的&#xff1f; 数组链表红黑树&#xff0c;和HashMap一样 Node数组&#xff1a; ConcurrentHashMap内部维护一个Node数组&#xff0c;其中每个Node就是键值对的存储单元。链表&#xff1a; 每个Node实际上是一个链表…

基于深度学习的果蔬检测识别系统(含UI界面、yolov5、Python代码、数据集)

项目介绍 项目中所用到的算法模型和数据集等信息如下&#xff1a; 算法模型&#xff1a;     yolov5 yolov5主要包含以下几种创新&#xff1a;         1. 添加注意力机制&#xff08;SE、CBAM、CA等&#xff09;         2. 修改可变形卷积&#xff08;DySnake-主…

MySQL之导入以及导出远程备份v

目录 一.navact数据导入导出 1.1 导入 1.2 导出 二. mysqldump命令导入导出数据 2.1 导入 2.2 导出 三.load data file进行数据导入导出&#xff08;只限于单表&#xff09; 3.1 导入 3.2 导出 四.远程连接 好啦就到这里了哦!!!希望帮到你哦!!! 一.navact数据导入导…

CSS响应式布局

目录 rem单位 媒体查询 rem 媒体查询 rem适配方案&#xff08;了解&#xff09; 响应式布局总结 rem单位 1.设置文字大小的单位 px&#xff1a;设置为固定的css像素 em&#xff1a;相对于父元素字体的大小 %&#xff1a;相对于父元素字体的大小 rem&#xff1a;相对于…

CF1165E

洛谷题目链接 Codeforces题目链接 分析 如果只算区间 1 1 1 到 n n n 的话那么将 a a a 升序 b b b 降序排序即可。 我们发现 a i a_i ai​ 一共要乘 i ( n − i 1 ) i\times(n-i1) i(n−i1) 次&#xff0c;所以可以直接将 a i a_i ai​ 乘 i ( n − i 1 ) i\t…