面试常客:手撕单例模式
设计模式、方法等
一.单例模式
1.定义:一个类只能有一个实例,并提供该实例的全局访问点。好处是有些实例在全局中只需要一个,使用单例模式可以避免一个全局使用的类(在自己项目当中就是user类)
2.设计要素
(1)一个私有构造函数
(2)一个私有静态变量
(3)一个公有静态函数
二.懒汉式(线程不安全)
1.先不创建实例,第一次被调用时创建
2.也没有synchronized,所以线程不安全,同时多线程条件下可能会实例化多个实例
3.有点是延迟了实例化,如果不使用该类,就不会被实例化
三.饿汉式(线程安全)
1.不管是否需要,直接实例化好(就像饿死鬼一样),然后需要的时候就直接调用方法
2.因为提前实例化好了,所以不需要考虑线程安全的问题
3.但也因为实例化好了,如果使用,就造成了资源的浪费
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {
}
public static Singleton getUniqueInstance() {
return uniqueInstance;
}
}
四.双重检查锁实现(线程安全) 突然发现就很顾名思义
1.首先需要检查两次
2.其次用synchronized保证了线程安全
3.相当于改进了的线程安全的懒汉模式,将锁的位置变了并多了一个检查,第一个判断是判断实例是否存在,锁之后的判断是只允许一个线程实例化,这样就只会在第一次的时候有线程阻塞的情况。
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
五.为什么要用volatile修饰uniqueInstance
因为新建一个对象分为3步:分配内存空间,初始化对象,将对象指向分配的内存地址;
但是jvm有指令重排的特性,单线程的时候没有问题,但多线程可能会导致有些线程获取没有初始化完成的实例。这时候就需要volatile,它可以禁止jvm的指令重排
六.静态内部类实现(线程安全)
1.外部类Singleton被加载的时候,SingletonHolder并没有被加载 ,调用getxx()方法的时候,才会运行并加载静态内部类,然后初始化实例,此时靠jvm来保证只被实例化一次
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getUniqueInstance() {
return SingletonHolder.INSTANCE;
}
}
七.枚举类实现
public enum Singleton {
INSTANCE;
//添加自己需要的操作
public void doSomeThing() {
}
}
八.使用场景
频繁实例化然后又销毁的对象,使用单例模式可以提高性能。
经常使用的对象,但实例化时耗费时间或者资源多,如数据库连接池,使用单例模式,可以提高性能,降低资源损坏。
使用线程池之类的控制资源时,使用单例模式,可以方便资源之间的通信。
原文地址:https://www.cnblogs.com/donkeyAndConcise/p/15085139.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- cordova run android 下载gradle报timeout
- How we redesign the NSQ-NSQ重塑之客户端
- [PHP] 使用php生成下载csv文件
- 深入浅出MySQL crash safe
- Cordova+React+Ant.design项目搭建
- ubuntu配置ZeroTier
- 有赞零售小票打印图片二值化方案
- 虚拟机中CentOS获取ip
- CentOS7 安装JDK8,tomcat8
- Py2和Py3共存相关问题
- 解决node-sass无法安装导致依赖安装失败
- 0307前端笔试题
- 有赞微商城-Android 组件化方案
- React Router v4相关
- 微信小程序文档学习笔记