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

红烧土豆泥 等级 1013 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();
        }
    }

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

收藏
评论区

相关推荐

Java单例模式7种写法,你是不是有用错过?
单例大家都很清楚的知道作用,也不多说,主要是在不同的情况下注意事项; 单例模式多种写法 1、饿汉式可用 //饿汉式 language private final static Singleton INSTANCE new Singleton(); private Singleton(){} public static Singleton
创建型模式之单例设计模式
什么是单例设计模式? 顾名思义,只有一个实例。 单例模式它主要是确保一个类只有一个实例,并且可以提供一个全局的访问点。 废话少说,直接上干货了 单例模式之饿汉式 所谓饿汉式,顾名思义,“ 它很饿 ”。所以说,它一旦被加载进来,就会直接实例化一个对象。 例如: language class Singleton { private static fin
JavaScript设计模式之单例模式
<section id"nice" datatool"mdnice编辑器" datawebsite"https://www.mdnice.com" style"fontsize: 16px; color: black; lineheight: 1.6; wordspacing: 0px; letterspacing: 0px; word
C#单例
单例模式: 步骤: 1.定义静态私有对象 2.构造函数私有化 3.定义一个静态的,返回值为该类型的方法,一般以Getinstance/getInit为方法名称 单例模式有懒汉和饿汉,最好使用饿汉 1.饿汉式---先实例化 public class Singleton { private stati
JAVA设计模式之单例设计模式
        单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。   在JAVA中实现单例,必须了解JAVA内存机制,JAVA中实例对象存在于堆内存中,若要实现单例,必须满足两个条件:   1.限制类实例化对象。即只能产生一个对象。
Java ASM 简单例子
###Test的代码比较简单 public class Test { /\*\* \* @param args \*/ public static void main(String\[\] args) { test01(); } static void test01() { System.out.println("Hello In Tes
Java单例模式
**什么是单例模式**   单例模式是在程序中,一个类保证只有一个实例,并提供统一的访问入口。 **为什么要用单例模式** * 节省内存 节省计算 * 如对象实例中的一样的,那就不用每次都创建一个对象 * 方便管理 * 因为单例提供一个统一的访问入口,不需要创建N多个对象,很多工具类都用了单例实现,如日志、字符串工具类 *
Java单例模式实现方式
懒汉式-非线程安全 --------- public class LazyNoSafe { private static LazyNoSafe instance; public static LazyNoSafe getInstance() { if (instance == null) {
Java多线程下单例
/* 多线程下的单例 */ //饿汉式 class Single { private static final Single s = new Single(); private Single(){} public static Single g
Java多线程编程之单例模式
延迟加载:“懒汉模式” ----------- 延迟加载是指在调用getInstance()方法时创建实例。常见的方法是在getInstance()方法中实例化new。实现代码如下: ![](https://oscimg.oschina.net/oscnet/0b194956e9fd68db32050dd6439225bb86a.png) 但是因为ge
java中单例模式的比较
单例模式可能是代码最少的模式了,但是少不一定意味着简单,想要用好、用对单例模式,还真得费一番脑筋。本文对Java中常见的单例模式写法做了一个总结,如有错漏之处,恳请读者指正。 ### 饿汉法: 就是在第一次引用该类的时候就创建对象实例,而不管实际是否需要创建。 public class Singleton {            pr
java枚举类单例示例
public class Singleton {     //私有化构造函数     private Singleton(){ }       //定义一个静态枚举类     static enum SingletonEnum{         //创建一个枚举对象,该对象先天为单例         INSTANCE;    
PHP单例模式
<?php /** * 设计模式之单例模式 * $_instance必须声明为静态的私有变量 * 构造函数和析构函数必须声明为私有,防止外部程序new * 类从而失去单例模式的意义 * getInstance()方法必须设置为公有的,必须调用此方法 * 以返回实例的一个引
ECharts.js 简单示例
[ECharts.js学习(一) 简单入门](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.cnblogs.com%2Fleoxuan%2Fp%2F6511123.html) =====================================================
Struts2单例和多例
struts2中action是多例的,即一个session产生一个action如果是单例的话,若出现两个用户都修改一个对象的属性值,则会因为用户修改时间不同,两个用户访问得到的属性不一样,操作得出的结果不一样.举个例子:有一块布长度300cm,能做一件上衣(用掉100cm)和一件裤子(用掉200cm);甲和乙同时访问得到的长度都是300cm,甲想做上