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) 感觉在介绍之前有必要阐述一 ...
随机推荐
- ptaCCF
返回首页 English站点地图联系我们常见问题CCF招聘登录 加入CCF 计算机 CCF简介 中国计算机学会(CCF)成立于1962年,全国性学会,独立社团法人,中国科学技术协会成员. CCF是 ...
- idea修改默认maven配置
idea修改默认maven配置 方法一 (不推荐) 打开project.default.xml文件,在其中加入如下几行配置. 代码如下 保存修改之后新建一个maven项目查看效果 方法二 新增Proj ...
- client-go实战之八:更新资源时的冲突错误处理
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<client-go实战> ...
- [ARC143B] Counting Grids 题解
Counting Grids 题目大意 将 \(1\sim n^2\) 填入 \(n\times n\) 的网格 \(A\) 中,对于每个格子满足以下条件之一: 该列中存在大于它的数. 该行中存在小于 ...
- Redis主从复制部署小结
Redis主从 搭建主从架构 单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离. 主从数据同步原理 全量同步 主从第一次建立连接时,会执行全量同 ...
- 安装了less后仍然报错:Error: Cannot find module 'less'
结果是命令有点问题,正常来说是用下面的: npm i less –save-dev-g 然后可以正常启动了: --------------------------------------------- ...
- 广义 SAM 学习笔记
开 CF 开到了一道广义 SAM,决定来学一学. 发现网上确实充斥着各种各样的伪广义 SAM,也看到了前人反复修改假板子的过程,所以试着来整理一下这堆奇奇怪怪的问题. 当然本文的代码也不保证百分百正确 ...
- Splay 详细图解 & 轻量级代码实现
学 LCT 发现有点记不得 Splay 怎么写,又实在不知道这篇博客当时写了些什么东西(分段粘代码?),决定推倒重写. 好像高一学弟也在学平衡树,但相信大家都比樱雪喵强,都能一遍学会!/kel 写在前 ...
- 子组件emit 父组件方法,成功后回调执行子组件方法
场景: 父组件 update方法 子组件 确定按钮 getlist 刷新列表 子组件点击确定按钮,调用父组件新增接口,新增成功以后,子组件列表刷新 子组件: emit("confirmPa ...
- Java实现两字符串相似度算法
1.编辑距离 编辑距离:是衡量两个字符串之间差异的度量,它表示将一个字符串转换为另一个字符串所需的最少编辑操作次数(插入.删除.替换). 2.相似度 计算方法可以有多种,其中一种常见的方法是将编辑距离 ...