创建型模式之单例设计模式

红烧土豆泥 等级 661 0 0
标签: 单例模式Java

什么是单例设计模式? 顾名思义,只有一个实例。 单例模式它主要是确保一个类只有一个实例,并且可以提供一个全局的访问点。 废话少说,直接上干货了~

单例模式之饿汉式 所谓饿汉式,顾名思义,“ 它很饿 ”。所以说,它一旦被加载进来,就会直接实例化一个对象。 例如:

  class Singleton {
    private static final Singleton SINGLE = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return SINGLE;
    }

    public void print() {
        System.out.println("hello,我是饿汉~ 哇咔咔~");
    }
}

接下来编写一个测试类

  @Test
    public void TestSingleton() {
        Singleton s = Singleton.getInstance();
        s.print();
    }

运行效果: 创建型模式之单例设计模式

结果异常顺利,就这样结束了吗?肯定不会就这样简单啦!我们再来看一下它在多线程的情况下运行效果如何?

  class Singleton {
    private static final Singleton SINGLE = new Singleton();

    private Singleton() {
        System.out.println("我出来啦~");
    }

    public static Singleton getInstance() {
        return SINGLE;
    }

    public void print() {
        System.out.println("hello,我是饿汉~ 哇咔咔~");
    }
}

测试类:

  @Test
    public void TestSingleton() {
        for (int i = 0; i < 3; i++) {
            new Thread(()->{
                Singleton s = Singleton.getInstance();
                s.print();
            }).start();
        }
    }

结果: 创建型模式之单例设计模式 可以看到,测试结果还是异常丝滑。

那让我们再来看看它兄弟 --> 单例模式之懒汉式 一听他名字,就知道它比较懒,肯定一上来就不会进行实例化,而是先判断,先问一下你有对象了吗?如果没有的话,再给你分配。 所以说,它的写法应该是:

  class Singletonss{
    private static Singletonss SING = null;

    private Singletonss() {
        System.out.println("我是懒汉,我出来啦~");
    }

    public static Singletonss getInstance() {
        if(SING == null) {
            SING = new Singletonss();
        }
        return SING;
    }

    public void print() {
        System.out.println("hello,我是懒汉~ 哇咔咔~");
    }

}

下面是一个测试类:

  @Test
    public void TestSingleton() {
        Singletonss s = Singletonss.getInstance();
        s.print();
    }

看一下运行结果: 创建型模式之单例设计模式 貌似是一切正常,风平浪静,没什么太大问题~ 然后,让我们再来偷偷瞅一下它在多线程的情况下是什么妖怪吧~ 还是用上面的懒汉式代码,然后编写一个测试

  @Test
    public void TestSingleton() {
        for(int i=0;i<3;i++) {
            new Thread(()->{
                Singletonss s = Singletonss.getInstance();
                s.print();
            }).start();
        }
    }

创建型模式之单例设计模式 是不是被突然跳出来的饿汉吓到了,我才开启了三个线程,他竟然出来了三次~ 让我们分析一下是什么原因吧!可能细心的小伙伴们已经想到,多线程情况下,每个线程都会竞相抢夺资源,所以说第一个线程它在执行if判断但还未进行new的时候,别的线程也可能进入了if判断,所以说就会出现饿汉单例被实例化多次的情况,如何解决勒,有的人可能回想直接给那个方法加synchronized关键字,每次只允许一个线程进入。没错,这样是可以解决掉这问题,但是,如果给方法加了同步,也就意味着,线程资源来到这之后,只能先进入一个,别的需要排队等待这,如果只有一两个线程还好,如果说有几千个线程在这,无疑这样会大大浪费了资源,拖慢了程序的进度,所以这种方法不是最优的。那如果是给if判断加同步嘞?

  public static Singletonss getInstance() {
        synchronized (Singletonss.class) {
            if(SING == null) {
                SING = new Singletonss();
            }
        }
        return SING;
    }

感觉上还是蛮好的,但是与上个方法没太大区别。那,这,,,咋整哇~ 其实我们可以让每个先到的线程先进入if判断,然后开启同步,然后再进行一次判断,让先来的去实例化,后来的一看已经被实例化好了,就可以直接返回了。这样可以很大程度上减少线程等待时间。具体实现代码如下:

  class Singletons {

    private static volatile Singletons single = null;

    private Singletons() {
        System.out.println("我是懒汉,我出来啦~");
    }

    public static Singletons getInstance() {
        if (single == null) {
            synchronized (Singleton.class) {
                if (single == null) {
                    single = new Singletons();
                }
            }
        }
        return single;
    }

    public void print() {
        System.out.println("hello,我是懒汉~ 哇咔咔~");
    }
}

测试类:

  @Test
    public void TestSingleton() {
        for(int i=0;i<3;i++) {
            new Thread(()->{
                Singletons s = Singletons.getInstance();
                s.print();
            }).start();
        }
    }

再来看一下与运行结果: 创建型模式之单例设计模式 一切正常

收藏
评论区

相关推荐

通过一个简单实例了解vuex
简单说明 什么是vuex,vuex怎么使用,什么场景下适合使用vuex, vuex 文档(https://links.jianshu.com/go?tohttps%3A%2F%2Fvuex.vuejs.org%2Fzh%2F)中都有介绍。看完文档之后,都知道vuex的核心有State、Getter、Mutation、Action、Modul
Java单例模式7种写法,你是不是有用错过?
单例大家都很清楚的知道作用,也不多说,主要是在不同的情况下注意事项; 单例模式多种写法 1、饿汉式可用 //饿汉式 language private final static Singleton INSTANCE new Singleton(); private Singleton(){} public static Singleton
创建型模式之单例设计模式
什么是单例设计模式? 顾名思义,只有一个实例。 单例模式它主要是确保一个类只有一个实例,并且可以提供一个全局的访问点。 废话少说,直接上干货了 单例模式之饿汉式 所谓饿汉式,顾名思义,“ 它很饿 ”。所以说,它一旦被加载进来,就会直接实例化一个对象。 例如: language class Singleton { private static fin
《java 核心技术》卷1 学习 概述 第一章Java程序设计概述
从浅面了解Java 1.Java 在语言得地位 现在有所下降 但仍是老大哥 所以值得学习 2.Java特性 1.简单性:从一方面来说 Java可以支持在小型机器上运行 必定不是很复杂得,所以上手不难 2.面向对象:Java有相比于其他的语言 更简单得接口
c++11 实现单例模式
C11出来后,里面新增加了好多好用的功能 下面的单例就是使用了C11中的标准库中的mutex和unique_prt 进行内存管理的. 此单例模式不用担心内存的释放问题 pragma once include <memory include <mutex template <class T class Singleton { public: ty
Spring Cloud OAuth2 微服务认证授权
OAuth 2.0 是用于授权的行业标准协议,它致力于简化客户端开发人员的工作,同时为 Web 应用、桌面应用、移动应用等各种客户端应用提供了特定的授权流程。本文讲解如何使用 OAuth2 协议来授权客户端应用访问 Spring Cloud 微服务。 微服务认证授权概述 单点登录 相比于单体应用,微服务应用需要在多个服务之间共享
【Flutter实战】Dart线程模型及异常捕获
2.6 Flutter异常捕获在介绍Flutter异常捕获之前必须先了解一下Dart单线程模型,只有了解了Dart的代码执行流程,我们才能知道该在什么地方去捕获异常。 2.6.1 Dart单线程模型在Java和ObjectiveC(以下简称“OC”)中,如果程序发生异常且没有被捕获,那么程序将会终止,但是这在Dart或JavaScript中则不会!
synchronized锁升级过程
1.前置知识:    1.1 JAVA对象的内存布局            hotspot虚拟机中,普通对象在堆中的存储可以划分成三部分:对象头(包含了MarkWord和类型指针)、实例例数据和padding。JAVA对象的内存布局MarkWord的长度为4byte/8byte,用于存储对象自身的运行时数据
JavaScript设计模式之单例模式
<section id"nice" datatool"mdnice编辑器" datawebsite"https://www.mdnice.com" style"fontsize: 16px; color: black; lineheight: 1.6; wordspacing: 0px; letterspacing: 0px; word
【单例深思】饿汉式
1、抛出问题1. 为什么饿汉式单例是线程安全的?2. 为什么饿汉式单例没有延迟加载(Lazy Loading)? 2、JVM类加载机制饿汉式单例的实现:javapublic class Singleton private static Singleton singleton new Singleton(); private S
go好用的类型转换第三方组件 [cast]
关于我 Cast介绍 Cast是什么?Cast是一个库,以一致和简单的方式在不同的go类型之间转换。Cast提供了简单的函数,可以轻松地将数字转换为字符串,将接口转换为bool类型等等。当一个明显的转换是可能的时,Cast会智能地执行这一操作。它不会试图猜测你的意思,例如,你只能将一个字符串转换为int的字符串表示形式,例如“8”。Cast是为Hugo开发的
2021年度最全面JVM虚拟机,类加载过程与类加载器
前言类装载器子系统是JVM中非常重要的部分,是学习JVM绕不开的一关。一般来说,Java 类的虚拟机使用 Java 方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表
2021年度最全面JVM虚拟机,类加载过程与类加载器
前言类装载器子系统是JVM中非常重要的部分,是学习JVM绕不开的一关。一般来说,Java 类的虚拟机使用 Java 方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。每个这样的实例用来表
Python基础7——单例模式
15 单例模式 15.1 init和new方法执行步骤1. 实例化一个对象,先执行new方法,在new方法中返回对象2. 然后再调用init方法 15.1.1 \\init\\方法init 是构造方法<font color"red"其实最先调用的方法是new方法</font,但是大部分情况下是不使用new方法pythonclass Test(object):
一篇文章带你了解CSS单位相关知识
大家好,我是皮皮,今天给大家分享一些前端的知识。 一、了解 CSS 单位测量长度的单位可以是绝对的,例如像素,点等,也可以是相对的,例如百分比(%)和 em 单位。指定 CSS 单位对于非零值是必须的,因为没有默认单位。丢失或忽略单位将被视为错误。但是,如果该值为 0,则可以省略该单位(毕竟,零像素与零英寸是一样的)。注意: 长度是指距离测量。长度包括数字值