单例模式

推荐 Java 常见面试题

什么是单例模式 ?

确保程序中一个类只能被实例化一次,实现这种功能就叫单例模式

单例模式的好处是什么 ?

  1. 方便控制对象
  2. 节省资源减少浪费

怎么实现单例模式 ?

  1. 构造私有化
  2. 调用静态方法返回实例
  3. 确保对象的实例只有一个

常见的单例模式有哪些 ?

  1. 饿汉式

把对象创建好,需要使用的时候直接用就行饥肠辘辘 非常着急

  1. 懒汉式
  • 由于饿汉式容易浪费资源,比如类里 有public static 修饰的一个方法 test(),即可不创建实例就可访问到
  • 不到万不得已不创建实例,什么时候用什么时候创建

懒汉式的缺点呢 ?

线程不安全 但是可以控制 如何控制,下面会讲

代码实现饿汉式

创建 Singleton.java

public class Singleton1 {

    public static final Singleton1 INSTANCE = new Singleton1();

    //构造方法私有化
private Singleton1(){ } //get方式获取对象
public static Singleton1 getInstance(){
return INSTANCE;
}
}

创建 TestSingleton.java

public class TestSingleton{
public static void main(String[] args) {
Singleton1 st1 = Singleton1.INSTANCE;
Singleton1 st2 = Singleton1.getInstance();
//return true
System.out.println(st1.hashCode() == st2.hashCode());
//return true
System.out.println(st1 == st2);
}
}

代码实现懒汉式

创建 Singleton2.java

public class Singleton2 {

    private static Singleton2 INSTANCE;

    //构造方法私有化
private Singleton2(){ } //get方式获取对象
public static Singleton2 getInstance(){
if (INSTANCE == null) {
INSTANCE = new Singleton2();
}
return INSTANCE;
}
}

x修改 TestSingleton.java

Singleton2 a = Singleton2.getInstance();
Singleton2 b = Singleton2.getInstance();
//ture
System.out.println(a == b);

注意: 再有的情况下懒汉式线程不安全比如多线程

举例说明 线程不安全

修改 Singleton2.java

public static Singleton2 getInstance(){
if (INSTANCE == null) {
try {
Thread.sleep((int) Math.random() * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Singleton2();
}
return INSTANCE;
}

修改 TestSingleton.java

Callable<Singleton2> c = new Callable<Singleton2>() {
@Override
public Singleton2 call() throws Exception {
return Singleton2.getInstance();
}
}; //创建两个线程池
ExecutorService es = Executors.newFixedThreadPool(2);
Future<Singleton2> f1 = es.submit(c);
Future<Singleton2> f2 = es.submit(c); Singleton2 a = f1.get();
Singleton2 b = f2.get();
/**
* 有可能两种情况
* 1. 判断是否一致:false
* 2. 判断是否一致:true
*/
System.out.println("判断是否一致:" + (a == b));

为什么会这样呢 ?

  • 因为第一个线程 if (INSTANCE == null) 进去之后触发 sleep() 线程休眠
  • 第二个线程就紧跟着 if (INSTANCE == null) 这时 INSTANCE 还是等于null,随后进入线程休眠
  • 这样他两个都创建了实例,一共创建两次所以导致线程不安全

怎么解决线程不安全 ?

解决 懒汉式 线程不安全的方法

  1. 使用 synchronized 同步锁
  2. 使用静态内部类
使用 synchronized 同步锁

修改 Singleton2.java

public static Singleton2 getInstance(){
//提高效率 已经new过后不需要再等着资源
if (INSTANCE == null) {
//可以使用同步锁 完成线程安全
synchronized (Singleton1.class) {
if (INSTANCE == null) {
try {
Thread.sleep((int) Math.random() * 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Singleton2();
}
}
}
return INSTANCE;
}
  • 再次运行 TestSingleton.java 测试 就会返回 true
  • 但是还是有一个问题,第一个线程已经创建好了,第二个线程还需要再次进入 synchronized块等待资源的控制权.可以在外面加上 if 判断 INSTANCE == null 即可提高效率
使用静态内部类

因使用 synchronized 同步锁,代码看起来不雅观,所以可以使用静态内部类,达到线程安全

修改 Singleton2.java

public class Singleton2 {

    //构造私有化
private Singleton2(){ } //在内部类被加载时,才创建
//静态内部类 不会随着外部类加载,初始化 它是一个独立的 当用这个类时才会加载初始化
//在内部类加载和初始化,所以线程是安全的
private static class Inner{
private static final Singleton2 INSTANCE = new Singleton2();
} //get 方式获取静态内部类的INSTANCE
public static Singleton2 getInstance(){
return Inner.INSTANCE;
}
}

小结

并不能说明 懒汉式 要强于 饿汉式,可以根据项目需求,来使用其中一种模式

再次推荐 保你面试必过的 java面试题

本文就先说到这里,有问题欢迎留言讨论

Java设计模式之单例模式 通俗易懂 超详细 【内含案例】的更多相关文章

  1. java 设计模式之单例模式

    -------Success is getting what you want, happiness is wanting what you get. java设计模式之单例模式(Singleton) ...

  2. 折腾Java设计模式之单例模式

    博文原址:折腾Java设计模式之单例模式 单例模式 Ensure a class has only one instance, and provide a global point of access ...

  3. Java设计模式之单例模式(七种写法)

    Java设计模式之单例模式(七种写法) 第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: public class Singleton { private static Singleto ...

  4. Java 设计模式之单例模式(一)

    原文地址:Java 设计模式之单例模式(一) 博客地址:http://www.extlight.com 一.背景 没有太多原由,纯粹是记录和总结自己从业以来经历和学习的点点滴滴. 本篇内容为 Java ...

  5. java设计模式1——单例模式

    java设计模式1--单例模式 1.单例模式介绍 1.1.核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点 1.2.常见场景 1.3.单例模式的优点 1.4.常见的五种单例模式实现 ...

  6. Java中的三大特性 - 超详细篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的三大特性 - 超详细篇>,希望对大家有帮助,谢谢 这一节的内容可能有点多,大家可以选择性的来看 简介 Java的三大特性:封装.继 ...

  7. java设计模式之单例模式你真的会了吗?(懒汉式篇)

    java设计模式之单例模式你真的会了吗?(懒汉式篇) 一.什么是单例模式? 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供 ...

  8. java设计模式之单例模式(七种方法)

    单例模式:个人认为这个是最简单的一种设计模式,而且也是在我们开发中最常用的一个设计模式. 单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个 ...

  9. java设计模式之单例模式(几种写法及比较)

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  10. java设计模式- (1)单例模式

    参加校园招聘的笔试,发现公司都会考一些java设计模式,所以上网查询相关内容,总结常用的几种单例模式. 单例模式(Singleton Pattern)是 Java中最简单的设计模式之一.这种类型的设计 ...

随机推荐

  1. P5494 题解

    来一发 \(O(\log n)\) 线性空间的解法. 考虑通过只维护线段树叶子节点的虚树的方法压缩空间,考虑记录下每个节点的编号,然后通过异或完求最低位的 \(1\) 的方式求出 LCA 的深度,然后 ...

  2. SQL注入方法

    目录 前言 如何测试与利用注入点 手工 注入思路 工具 sqlmap -r -u -m --level --risk -v -p --threads -batch-smart --os-shell - ...

  3. acwing 875

    acwing875 题目大意:快速幂模板题 Train of thought 此题如果采用暴力的做法时间复杂度为0(n*b); n为样例的数目,b是幂 我们想要优化暴力的做法,首先样例的数量是没有办法 ...

  4. Windows系统下DoH配置小记

    Windows系统下DoH配置小记 浏览器 Edge 打开edge://settings/privacy 使用安全的 DNS 指定如何查找网站的网络地址 设置自定义服务商为https://doh.op ...

  5. 判断C盘下有没有Templets文件夹,没有则新建,然后判断Templets文件夹下有没有TEST.xlt文件

    VB.NET 判断C盘下有没有Templets文件夹,没有则新建,然后判断Templets文件夹下有没有TEST.xlt文件,如果没有则新建   你可以使用VB.NET中的Directory和File ...

  6. Arch Linux install i3-wm

    Arch Linux install i3-wm 简介 i3-wm 是一种动态的平铺式窗口管理器,它的设计目标是提供一个快速.简洁.可定制的桌面环境,适合开发者和高级用户使用.它有以下几个特点: 它使 ...

  7. Kmesh v0.4发布!迈向大规模 Sidecarless 服务网格

    本文分享自华为云社区<Kmesh v0.4发布!迈向大规模 Sidecarless 服务网格>,作者: 云容器大未来. 近日 Kmesh 发布了 v0.4.0 版本,感谢社区的贡献者在两个 ...

  8. Excel快速下拉填充序列至10000行

    问题:想要下拉输入的数据递增得到1.2.3--10000,但是手动下拉太累 解决: 1.如在A1单元格输入1,在A2单元格输入2 2.选中A2单元格,在上方名称框中填写A2:A1000,回车,此时将选 ...

  9. SpringSecurity:hasAuthority与自定义权限校验

    springsecurity中有两种权限控制方法 1.基于注解 @PreAuthorize("hasAuthority('syst:add')") 他的作用是在controller ...

  10. Codeforces Round 947 (Div. 1 + Div. 2) A~H

    Codeforces Round 947 (Div. 1 + Div. 2) A 模拟. B 最小的 \(a\) 肯定作为 \(i\).对于不被 \(i\) 整除的,最小的那个作为 \(j\),判断是 ...