栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

简单了解单例模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

简单了解单例模式

一、前言

单例模式是指在内存中有且只会创建一次对象的设计模式,在程序中多次使用同一个对象且作用相同的时候,为了防止频繁的创建对象,单例模式可以让程序在内存中创建一个对象,让所有的调用者都共享这一单例对象。单例模式的类型有两种:懒汉式和饿汉式。

二 单例模式类型

饿汉式:在类加载的时候已经创建好该单例对象。
懒汉式:在需要使用对象的时候才会去创建对象

2.1 饿汉式:

//饿汉式
public class Hungry {
 
    
    private Hungry() {
    }
 
    private final static Hungry HUNGRY = new Hungry();
 
    public static Hungry getInstance(){
        return HUNGRY;
    }

大家都知道饿汉式单例是程序启动的时候就已经创建好了对象,那么这样的会会有什么问题呢?有可能浪费空间,为什么呢?因为如果在该类中声明了许多内存空间,但却没有使用的话,就很浪费内存空间,因为饿汉式它是在程序启动的时候就已经创建好了。

2.2 懒汉式:

//懒汉式单例
public class LazySingle {
 
    private LazySingle(){
 
    }
    private static LazySingle lazySingle;
 
    public static LazySingle getInstance(){
        if (lazySingle == null ) {
            lazySingle = new LazySingle();
        }
        return lazySingle;
    }
}

2.3 双重检查锁:

但是这样会不会有问题呢?这样创建的懒汉式单例模式在单线程环境下肯定是没问题的,但是在多线程环境下,就会有问题了。就会不止创建一个对象了,那么如何改进呢?如下:

//懒汉式单例
public class LazySingle {
 
    private LazySingle(){
        System.out.println(Thread.currentThread().getName()+"ok");
    }
    private static LazySingle lazySingle;
 
    //双重检查加锁
    public static LazySingle getInstance(){
        if (lazySingle == null ){
            synchronized (LazySingle.class){
                if (lazySingle == null ) {
                    lazySingle = new LazySingle();
                }
            }
        }
        return lazySingle;
    }

这就是双重检查加锁的机制了(DCL懒汉式),这样就可以保证在多线程环境下有且仅会创建一个对象。

2.4 volatile防止指令重排:

那么这样的双重检查锁是完整的吗,会不会出现一些其他的问题呢?其实也是会的,因为当我们在 new LazySingle()的时候,其实是有可能发生指令重排的。

1 分配内存空间
2 执行构造方法,初始化对象
3 把这个对象指向这个空间

正常情况下,执行的这个顺序是1,2,3,如果在发生了指令重排,并且在多线程的环境下,也会出现问题。比如:A线程指令重排1,3,2,那么在重排过程中线程B进来,发现lazySingle已经分配内存空间了,不等于null了,那么就直接返回了,对于这种情况应该怎样处理呢?可以使用volatile关键字来解决,如下:

//懒汉式单例
public class LazySingle {
 
    private LazySingle(){
        System.out.println(Thread.currentThread().getName()+"ok");
    }
    private volatile static LazySingle lazySingle;
 
    //双重检查加锁
    public static LazySingle getInstance(){
        if (lazySingle == null ){
            synchronized (LazySingle.class){
                if (lazySingle == null ) {
                    lazySingle = new LazySingle();
                }
            }
        }
        return lazySingle;
    }
 }

2.5 静态内部类

//静态内部类
public class Holder {
 
    private Holder(){
 
    }
    public static Holder getInstance(){
        return InnerClass.HOLDER;
    }
 
    public static class InnerClass{
        private static final Holder HOLDER = new Holder();
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1032273.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号