Java单例模式的几种常见实现方式
Java单例模式的几种常见实现方式
懒汉or饿汉?
- 懒汉:单例模式延迟加载方式,一开始不给你new对象,你要new再给你new
- 饿汉:上来就给你new好一个对象,你可以直接用(吃),你也没法new
饿汉:不加锁,线程安全,用起来方便,容易产生垃圾对象
public class SingletonTest1 {
public static void main(String[] args) {
//由于构造方法是私有的,则外界无法实例化该类
//Singleton1 singleton1 = new Singleton1();
new Thread(() -> {
Singleton1 singleton1 = Singleton1.getInstance();
}).start();
Singleton1 singleton2 = Singleton1.getInstance();
}
}
class Singleton1 {
//类加载时直接通过声明调用构造方法初始化
private static volatile Singleton1 singleton1 = new Singleton1();
//让构造函数为private,这样该类不会被外部调用实例化对象
private Singleton1(){
check();
}
//通过静态方法提供外界获取该唯一可用对象的窗口
//直接给你用,你也别想着什么时候创建了
public static Singleton1 getInstance() {
return singleton1;
}
//第一次创建实例就打印
private static void check() {
System.out.println("第一次创建该类的唯一实例才会打印这句话");
}
}
输出:
第一次创建该类的唯一实例才会打印这句话
单线程下的单例模式(懒汉,线程不安全)
这种方式只能在单线程环境中实现单例模式
public class SingletonTest1 {
public static void main(String[] args) {
//由于构造方法是私有的,则外界无法实例化该类
//Singleton1 singleton1 = new Singleton1();
//只可以通过实例化的方式
Singleton1 singleton1 = Singleton1.getInstance();
Singleton1 singleton2 = Singleton1.getInstance();
singleton1.test();
}
}
class Singleton1 {
//默认初始化为null
private static Singleton1 singleton1;
//让构造函数为private,这样该类不会被外部调用实例化对象
private Singleton1(){}
//通过静态方法提供外界获取该唯一可用对象的窗口
//如果唯一的实例没有创建就负责创建,否则返回唯一的对象引用
public static Singleton1 getInstance() {
if (singleton1 == null) {
check();
singleton1 = new Singleton1();
}
//第二次创建就不会新建一个对象,而是传回之前已经创建的对象实例
return singleton1;
}
//一个实例方法,用于证明实例化成功
public void test() {
System.out.println("测试方法,证明确实获得到了唯一实例");
}
//第一次创建实例就打印
private static void check() {
System.out.println("第一次创建该类的唯一实例才会打印这句话");
}
}
输出:
第一次创建该类的唯一实例才会打印这句话
//显然第二次获取实例时只是获得到了之前创建的实例
测试方法,证明确实获得到了唯一实例
多线程下的单例模式(一)(懒汉,线程安全)
区别在于将方法上锁(这里也可以采用重入锁),我们来分析一下具体的工作环境,A线程为了检测是否新建的了实例,对get方法上锁,开始检测对象是否为null,并调用构造方法,返回对象...B线程试图中途获得锁被阻塞,然后等A线程释放锁之后,B获得锁去检测是否创建了对象,发现已经创建,就返回对象释放锁...
public class SingletonTest1 {
public static void main(String[] args) {
//由于构造方法是私有的,则外界无法实例化该类
//Singleton1 singleton1 = new Singleton1();
new Thread(() -> {
Singleton1 singleton1 = Singleton1.getInstance();
}).start();
Singleton1 singleton2 = Singleton1.getInstance();
}
}
class Singleton1 {
//默认初始化为null
private static Singleton1 singleton1;
//让构造函数为private,这样该类不会被外部调用实例化对象
private Singleton1(){}
//通过静态方法提供外界获取该唯一可用对象的窗口
//如果唯一的实例没有创建就负责创建,否则返回唯一的对象引用
public synchronized static Singleton1 getInstance() {
if (singleton1 == null) {
check();
singleton1 = new Singleton1();
}
//第二次创建就不会新建一个对象,而是传回之前已经创建的对象实例
return singleton1;
}
//一个实例方法,用于证明实例化成功
public void test() {
System.out.println("测试方法,证明确实获得到了唯一实例");
}
//第一次创建实例就打印
private static void check() {
System.out.println("第一次创建该类的唯一实例才会打印这句话");
}
}
输出:
第一次创建该类的唯一实例才会打印这句话
多线程下的单例模式(二)(双重检测)
这里要注意:上锁解锁的很消耗时间空间的,而这里无论对象是否存在,都先上锁,再去检测,显然是没有必要的,当线程很多的时候会造成资源大量的浪费~可以先检测对象是否存在,如果对象不存在再试图申请锁去创建资源,则会节约资源并达到线程安全的目的——双重检测
public class SingletonTest1 {
public static void main(String[] args) {
//由于构造方法是私有的,则外界无法实例化该类
//Singleton1 singleton1 = new Singleton1();
new Thread(() -> {
Singleton1 singleton1 = Singleton1.getInstance();
}).start();
Singleton1 singleton2 = Singleton1.getInstance();
}
}
class Singleton1 {
//默认初始化为null,volatile:主内存 工作内存
private static volatile Singleton1 singleton1;
//让构造函数为private,这样该类不会被外部调用实例化对象
private Singleton1(){}
//通过静态方法提供外界获取该唯一可用对象的窗口
//如果唯一的实例没有创建就负责创建,否则返回唯一的对象引用
public static Singleton1 getInstance() {
if (singleton1 == null) {
synchronized (Singleton1.class) {
//两个贤臣可能都越过了外层的null检测,所以可能进入后已经不是null了
if (singleton1 == null) {
check();
singleton1 = new Singleton1();
}
}
}
return singleton1;
}
//一个实例方法,用于证明实例化成功
public void test() {
System.out.println("测试方法,证明确实获得到了唯一实例");
}
//第一次创建实例就打印
private static void check() {
System.out.println("第一次创建该类的唯一实例才会打印这句话");
}
}
Java单例模式的几种常见实现方式的更多相关文章
- java单例模式的几种写法比较
概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...
- Java 单例模式的七种写法
Java 单例模式的七种写法 第一种(懒汉,线程不安全) public class Singleton { private static Singleton instance; private Sin ...
- 单例模式:Java单例模式的几种写法及它们的优缺点
总结下Java单例模式的几种写法: 1. 饿汉式 public class Singleton { private static Singleton instance = new Singleton( ...
- Linux下几种常见压缩方式测试对比
目录 Linux下几种常见压缩方式测试对比 参考 简介 测试 总结 Linux下几种常见压缩方式测试对比
- JAVA中的四种JSON解析方式详解
JAVA中的四种JSON解析方式详解 我们在日常开发中少不了和JSON数据打交道,那么我们来看看JAVA中常用的JSON解析方式. 1.JSON官方 脱离框架使用 2.GSON 3.FastJSON ...
- Redis 的几种常见使用方式
常见使用方式 Redis 的几种常见使用方式包括: Redis 单副本 Redis 多副本(主从) Redis Sentinel(哨兵) Redis Cluster Redis 自研 各种使用方式的优 ...
- java中的线程(2):如何正确停止线程之3种常见停止方式
1.常见停止方式 自定义线程,其中含退出标志位,在run中判断它. 使用interrupt()方法中断线程 使用stop方法暴力终止(已经弃用) 2.使用标志位 class TestThread ex ...
- java中的线程(2):如何正确停止线程之2种常见停止方式
1.常见停止方式 结束run函数,run中含退出标志位. 使用interrupt()方法中断线程 使用stop方法暴力终止(已经弃用) 2.结束run class TestThread extends ...
- Java单例模式的6种写法
在Java中,单例有很多种写法,面试时,手写代码环节,除了写算法题,有时候也会让手写单例模式,这里记录一下单例的几种写法和优缺点. 初级写法 懒汉式 饿汉式 双锁检验 内部类 枚举式 1.初级写法 p ...
- java实践经验几种常见数据库连接池的使用比较
经历的几个产品及项目中,包括了各种数据库及应用服务器,基本上几种常见的数据库连接池都用到了,根据使用的情况把这些连接池比较一下吧.(http://m.0834jl.com) 感觉在介绍之前有必要阐述一 ...
随机推荐
- Python学习 —— 初步认知
写在前面 Python是一种流行的高级编程语言,具有简单易学.代码可读性高.应用广泛等优势.它是一种解释型语言,可以直接在终端或集成开发环境(IDE)中运行,而无需事先编译. Python的安装 Py ...
- pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simpleLooking in indexes: https://pypi.tuna.t ...
- 《流畅的Python》 读书笔记 第二章数据结构(2) 231011
2.5 对序列使用+和* 通常 + 号两侧的序列由相同类型的数据所构成,在拼接的过程中,两个被操作的序列都不会被修改,Python 会新建一个包含同样类型数据的序列来作为拼接的结果 +和*都遵循这个规 ...
- C# ref, in, out关键字
写在前面:大内老A的这篇"老生常谈:值类型VS引用类型"放在微信收藏里好几个月了,终于趁着要讲JAVA传参机制的时候仔细地按照这篇博客,自己写代码跑一下,对C#的传参,ref,in ...
- 安装 Android x86 并开启 arm 兼容
安装 Android x86 并开启 arm 兼容 Win 11 下开启了 Hyper-v,尝试了各种安卓模拟器,要么不能设置代理(BlueStacks),要么/system目录没办法设置. 获取 A ...
- 《最新出炉》系列初窥篇-Python+Playwright自动化测试-24-处理单选和多选按钮-上篇
1.简介 在工作和生活中,经常会遇到我们需要进行选择的情况,比如勾选我们选择性别,男女两个性别总是不能同时选中的,再比如我们在选择兴趣爱好时,我们可以选择多个自己感兴趣的话题,比如:篮球.足球.电竞等 ...
- JS toFixed()方法精度丢失解决方法
JS toFixed()方法精度丢失 toFixed()方法可把Number四舍五入为指定小数位数的数字.但这个方法并不完全遵从四舍五入的规则,如 2.485.toFixed(2) //=>2. ...
- pnpm 管理依赖包是如何节省磁盘空间的?
npm 存在的问题 我们经常使用 npm 来管理 node 项目中的包,从 package.json 中读取配置将依赖下载到本地,以保障项目的正常运行. 当项目数量多时,这样的包管理方式会非常的占用电 ...
- 一个NET8 AOT编译的辅助项目,让你的任何可执行应用快速部署为服务
不知道大家有没有和小编一样,很多时候想将自己的一些应用转为服务运行,比如一些控制台应用或者.NET Core应用,但是又不想重新编码,把他们转为服务,本文将给大家提供些我使用过的方法,并提供一个基于N ...
- 提升效率,打通万里牛ERP与下游用友U8财务软件的无缝对接
一.对接流程 1.1 销售/售后流程 在万里牛订单出库后,通过轻易云数据集成平台将数据推送至用友U8销售订单和销售出库单,这些单据可以进行关联操作. 当万里牛售后单完成退货入库后,通过数据集成平台将数 ...