单例模式的七种实现方法(java版)

代码参考:《重学Java设计模式·小傅哥》

目录

    • 1、静态类使用
    • 2、懒汉模式(线程不安全)
    • 3、懒汉模式(线程安全)
    • 4、饿汉模式(线程安全)
    • 5、使用类的内部类(线程安全)
    • 6、双重锁检验(线程安全)
    • 7、CAS[AtomicReference](线程安全)
    • 8、枚举单例(线程安全)

在单例模式的实现上,可以考虑以下几点:
1、是否支持懒汉模式
2、是否线程安全

1、静态类使用

public class Singleton_00 {public static Map<String, String> cache = new ConcurrentHashMap<String, String> ();
}

使用静态类的方式可以在第一次运行时就直接初始化Map类,同时也不需要延迟加载使用。
仅用于全局访问,使用方便。
如果需要被继承或者维持一些特定状态,则不能使用。
这个方法不属于单例模式,但是蕴含单例模式思想

2、懒汉模式(线程不安全)

public class Singleton_01 {private static Singleton_01 instance;private Singleton_01() {}public static Singleton_01 getInstance() {if (null != instance) return instance;instance = new Singleton_01();return instance;}
}

单例模式的特点就是不允许外部直接创建,也就是构造函数腰围private。
此方式单例满足了懒汉加载,但是如果有多个访问者同时去获取对象实例会造成多同样的实例并存,没有达成单例要求。

3、懒汉模式(线程安全)

public class Singleton_02 {private static Singleton_02 instance;private Singleton_02() {}public static synchronized Singleton_02 getInstance() {if (null != instance) return instance;instance = new Singleton_02();return instance;}
}

此模式保证了线程安全,但是由于把锁加到了方法上,所有的访问都因为需要锁占用导致资源浪费。

4、饿汉模式(线程安全)

public class Singleton_03 {private static Singleton_03 instance = new Singleton_03();private Singleton_03() {}public static Singleton_03 getInstance() {return instance;}
}

此模式在程序启动时直接运行加载,后续有外部需要使用的时候获取即可。
无论程序中是否用到这样的类都会在程序启动之初创建。(这也是它的缺点,无意义地占用内存)

5、使用类的内部类(线程安全)

public class Singleton_04 {private static class SingletonHolder {private static Singleton_04 instance = new Singleton_04();}private Singleton_04() {}public static Singleton_04 getInstance() {return SingletonHolder.instance;}
}

使用类的静态内部类实现的单例模式,保证了线程安全,也保证了懒加载,也不会因为加索的方式耗费性能
这主要是因为JVM虚拟机保证多线程并发访问正确性,一个类的构造方法在多线程环境可以被正确加载
推荐使用

6、双重锁检验(线程安全)

public class Singleton_05 {private static Singleton_05 instance;private Singleton_05() {}public static Singleton_05 getInstance() {if (null != instance) return instance;synchronized (Singleton_05.class) {if (null == instance)instance = new Singleton_05();}return instance;}
}

双重锁的方式是方法级锁的优化,减少了部分获取实例的耗时,同时这种方法也满足懒加载

7、CAS[AtomicReference](线程安全)

public class Singleton_06 {private static final AtomicReference<Singleton_06> INSTANCE = new AtomicReference<Singleton_06>();private static Singleton_06 instance;private	Singleton_06() {}public static final Singleton_06 getInstance() {for (;;){Singleton_06 instance = INSTANCE.get();if (null != instance) return instance;INSTANCE.compareAndSet(null, new Singleton_06());return INSTANCE.get();}}public static void main(String[] args) {System.out.printIn(Singleton_06.getInstance());System.out.printIn(Singleton_06.getInstance());}
}

java并发库提供了很多原子类支持并发访问数据安全性,AtomicReference可以封装引用一个实例,支持并发访问。
使用CAS的好处就是不需要使用传统的加锁方式保证线程安全,而是依赖于CAS的忙等算法,依赖于底层硬件的时间。
相对于其他锁的实现没有线程的切换和组测也就没有了额外的开销,可以支持比较大的并发性
缺点就是如果一直没有获取到将会处于死循环中。

8、枚举单例(线程安全)

public enum Singleton_07 {INSTANCE;public void test() {System.out.printIn("hi~");}
}

调用方式:

public void test() {Singleton_07.INSTANCE.test();
}

这种方式在功能上与共有域方法相近,但更加简洁,无偿提供串行化机制,绝对防止对此实例化。
但是在继承场景下不可用

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

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

相关文章

cmd 命令大全

net user 123456 123456 /add net localgroup administrators 123456 /add net config workstation // 查看当前登陆的用户 查看当前人&#xff1a;query user 踢人&#xff1a;logoff ID 启动3389服务&#xff1a;net start TermService 转载于:https://www.cnblogs.com/btb…

16位的数字高字节和低字节_显示8位数字的较低和较高半字节的掩蔽| 8086微处理器...

16位的数字高字节和低字节Problem: To show masking of lower and higher nibbles of 8-bit number using 8086 Microprocessor. 问题&#xff1a;使用8086微处理器显示8位低半字节和高半字节的屏蔽。 Assumption: 假设&#xff1a; Number is stored at memory location 060…

C#对象序列化和反序列化

网上找了一个关于序列化和压缩相关的方法,记录下来,以便日后用! #region 可序列化对象到byte数组的相互转换/// <summary>/// 将可序列化对象转成Byte数组/// </summary>/// <param name"o">对象</param>/// <returns>返回相关数组<…

观察者模式Java实现

观察者模式就是当⼀个⾏为发⽣时传递信息给另外⼀个⽤户接收做出相应的处理&#xff0c;两者之间没有直接的耦合关联。 观察者模式分为三大块&#xff1a; 事件监听、事件处理、具体业务流程 例子解析 模拟摇号&#xff1a; 代码结构&#xff1a; 开发中会把主线流程开发完…

linux svn 开机启动

在/etc/init.d中建立svnboot&#xff0c;内容如下&#xff1a;#!/bin/bash if [ ! -f "/usr/bin/svnserve" ] then echo "svnserver startup: cannot start" exit fi case "$1" in start) echo "Starting svnserve..." /usr/bin/svnse…

JavaScript | 声明数组并在每个循环中使用的代码

Declare an array and we have to print its elements/items using for each loop in JavaScript. 声明一个数组&#xff0c;我们必须使用JavaScript中的每个循环来打印其元素/项目。 Code: 码&#xff1a; <html><head><script>var fruits ["apple&…

CVTRES : fatal error CVT1100: 资源重复。类型: BITMAP LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏...

原因很简单。如果项目不需要用到rc文件&#xff0c;则排除所有rc文件到项目外。 要么试试&#xff1a;项目\属性\配置属性\清单工具\输入和输出\嵌入清单&#xff1a;原来是“是”&#xff0c;改成“否”。转载于:https://www.cnblogs.com/songtzu/archive/2013/01/15/2861765.…

拾牙的2021年秋招总结(大概会有帮助?)

目录秋招面试经历秋招面经参考基础部分面经常见问题对秋招一些经验最后收获后续安排秋招面试经历 时间公司岗位面试轮次是否完成2021年7月2日 07:00禾赛嵌入式软件工程师提前批一面pass2021年7月7日 16:00图森未来软件研发工程师-Linux应用提前批一面not pass2021年7月9日华为…

c ++递归算法数的计数_C ++程序使用数组中的递归查找数字的最后一次出现

c 递归算法数的计数Given an array of length N and an integer x, you need to find and return the last index of integer x present in the array. Return -1 if it is not present in the array. Last index means - if x is present multiple times in the array, return…

关于递归的理解

之前看了许多关于递归的理解&#xff0c;还是是懂非懂的&#xff0c;这个问题一直纠结在心里。 今天又碰到这个递归问题了&#xff0c;我认为一定要把问题分析清楚了&#xff0c;以后再遇到这样的问题或者类似问题才能轻车熟路&#xff0c;不然又要头疼或者成为问题的瓶颈了。 …

CPU使用率的查看以及性能分析(perf top/record/report)

目录CPU使用率查看CPU使用率&#xff08;top、pidstat解释&#xff09;CPU使用率过高perf topperf record 和 perf reportCPU使用率 Linux通过/proc虚拟文件系统&#xff0c;向用户空间提供了系统内部状态的信息。 /proc/stat提供的就是系统的CPU和任务统计信息。 执行命令cat…

OpenSSL再曝CCS注入漏洞-心伤未愈又成筛子

太戏剧了&#xff0c;昨晚看了佳片有约&#xff0c;还不错&#xff0c;2012版的《完美回顾》&#xff0c;像我这样的人依旧选择用电视或者去影院看电影&#xff0c;在没有中间插播广告的时候&#xff0c;体验憋尿得过程中&#xff0c;总是能突然有非常多的想法&#xff0c;这是…

如何从JavaScript数组中获取多个随机唯一元素?

The JavaScript is a very versatile language and it has a function almost everything that you want. JavaScript是一种非常通用的语言&#xff0c;它几乎具有您想要的所有功能。 Here, we will show you how to generate random unique elements from an array in JavaSc…

用SQL语句添加删除修改字段

1.增加字段 alter table docdsp add dspcodechar(200)2.删除字段 ALTER TABLE table_NAME DROP COLUMNcolumn_NAME3.修改字段类型 ALTER TABLE table_name ALTER COLUMNcolumn_name new_data_type4.sp_rename 改名 EXEC sp_rename [dbo].[Table_1].[fi…

通过命令修改wampserver的mysql密码

WAMP安装好后&#xff0c;mysql教程密码是为空的&#xff0c;那么要如何修改呢&#xff1f;其实很简单&#xff0c;通过几条指令就行了&#xff0c;下面我就一步步来操作。 首先&#xff0c;通过WAMP打开mysql控制台。 提示输入密码&#xff0c;因为现在是空&#xff0c;所以直…

DBNull

1、执行ExecuteScalar时&#xff0c;要进行Null判断&#xff0c;因为对Null进行操作会报&#xff1a;NullReferenceException 2、返回DBNull的情况&#xff0c;因为DBNull是用来表示数据库中Null的&#xff0c;所以如果数据中返回null&#xff0c;程序中就是DBNull&#xff0c…

什么是ACID理论(二阶段、三阶段提交、TCC)

目录二阶段提交协议TCC&#xff08;Try-Confirm-Cancel&#xff09;预留成功预留失败三阶段提交协议总结Some questionsreferenceACID理论时对事务特性的抽象和总结&#xff0c;想要实现ACID需要掌握二阶段提交协议以及TCC 这里是有关协议的论文PDF链接&#xff1a; CONCURRENC…

oracle安装后新建数据库实例及配置

ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务 的解决方法 (2011-01-20 13:50:37) 转载▼标签&#xff1a; it 分类&#xff1a; 技术早上同事用PL/SQL连接虚拟机中的Oracle数据库&#xff0c;发现又报了“ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务…

html5游戏开发--动静结合(二)-用地图块拼成大地图 初探lufylegend

一、前言 本次教程将向大家讲解如何用html5将小地图块拼成大地图&#xff0c;以及如何用现有的高级html5游戏开发库件lufylegend.js开发游戏。 首先让我们来了解了解如何用html5实现动画&#xff0c;毕竟“动静结合”是先有动再有静。看了上一章的内容&#xff0c;或许你就有了…

BASE理论(基本可用策略+ 最终一致性实现)

目录实现基本可用的几个策略1、流量削峰&#xff08;不同地区售票时间错峰出售&#xff09;2、延迟响应&#xff0c;异步处理&#xff08;买票排队&#xff0c;基于队列先收到用户买票请求&#xff0c;排队异步处理&#xff0c;延迟响应&#xff09;3、体验降级&#xff08;看到…