纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

Java单例模式 Java设计模式之单例模式

吾日三省贾斯汀   2021-10-12 我要评论
想了解Java设计模式之单例模式的相关内容吗吾日三省贾斯汀在本文为您仔细讲解Java单例模式的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Java设计模式,Java单例模式下面大家一起来学习吧。

什么是设计模式?

百科:

设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

设计模式是软件行业的通用的设计标准在Java同样通用主要有23种设计模式如下:

在这里插入图片描述

有的小伙伴可能会问这么多学得完吗?

答:不好意思不要太自信了一般人还真学不完不过一些常用的设计模式例如上图中标红的单例模式、工厂模式、代理模式等设计模式还是需要花些时间和精力去多多了解一下相信会对自己在程序设计或写代码时有很大的帮助。

本文主要来聊一聊设计模式中创建型的单例模式进入正文~

单例模式是什么?

学习Java的小伙伴相信都写过Class类吧创建某个类实例化对象的核心是new MyClass()来实现如果没有任何设计规范在日常开发写代码时如果实例被用的地方很多每次调用的时候都通过new MyClass()得到实例化对象代码重复而且频繁的创建对象还影响性能而有些场景我们只需要提供该类的一个实例即可例如平时比较常见的线程池、日志对象、缓存等一般只需要确保有一个实例即可这种确保某个类只有一个实例并且能够类自身提供自动创建实例化对象的设计模式即称为单例模式。

单例模式设计的原则是什么?

  • 构造方法私有化:既然是单例就不能将类的构造函数暴露在外面因此需要重写构造函数为私有化;
  • 要考虑线程安全:多线程环境下要确保不会构造出多个实例对象。

Java实现单例模式的5种方式?

关于Java实现单例模式的有几种方式网上有很多说法有5种、6种甚至7种实现方式本文出于单例模式设计的两个主要原则构造方法私有化和要考虑线程安全不考虑线程安全的其他实现方式没有任何意义主要有5种实现方式:

在这里插入图片描述

懒汉

使用懒汉式写法主要是通过synchronized修饰实例化方法getInstance保证了线程安全并且只有调用getInstance时才初始化顾此得名懒汉。

懒汉写法1:

/**
 * 单例模式之懒汉写法1
 */
public class Singleton {
    private static Singleton instance = null;
    private Singleton(){}
    public synchronized static Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

懒汉写法2:

该写法等价于写法1原因在于关键字synchronized的灵活运用放在方法上修饰加锁的对象是Singleton等效于将synchronized移到方法内部作为一个同步块并通过括号中的Singleton.class显示指定锁对象效果是一样的。

/**
 * 单例模式之懒汉写法2
 */
public class Singleton {
    private static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        synchronized(Singleton.class) {
            if (instance == null) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}

饿汉

饿汉写法只需要定义一个static静态变量instance = new Singleton()简单的理解为在类加载时也会完成单例对象的实例化工作。

/**
 * 单例模式之饿汉
 */
public class Singleton {
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return instance;
    }
}

细心的小伙伴会发现该过程并没有使用到synchronized关键字那会不会线程不安全呢?答案是不会如果你大概了解过Java虚拟机即JVM(Java Virtual Machine)那你可能知道类加载过程为:加载 -> 验证 ->解析 ->初始化而初始化阶段是执行类构造器<clinit>()方法的过程<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合成产生的。

《深入理解Java虚拟机》类加载机制章节部分说明:

虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确地加锁、同步如果多个线程同时如初始化一个类那么只会有一个线程去执行这个类的<clinit>()方法其他线程都需要阻塞等待知道活动线程执行<clinit>()方法完毕。

静态内部类

静态内部类这种方式其实就是在类的内部创建一个static SingletonInner静态内部类然后在静态内部类的内部再定义一个static final修饰的静态常量INSTANCE = new Singleton()同样static修饰的SingletonInner静态内部类会在JVM加载类时完成类的初始化并完成自己定义的静态常量单例实例化过程。

/**
 * 单例模式之静态内部类
 */
public class Singleton {
    private static class SingletonInner{
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton(){}
    public static Singleton getInstance(){
        return SingletonInner.INSTANCE;
    }
}

双重校验锁DCL(Double Check Lock)

DCL写法其实与单例模式之懒汉写法2区别在于synchronized同步块外面再套一层判断并且使用了能确保线程安全核心volatile关键字修饰instance表明单例变量是内存共享的能够保证在多线程环境下的即时可见性。

/**
 * 单例模式之双重校验锁DCL
 */
public class Singleton {
    private volatile static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance(){
        if ( instance  == null ){
            synchronized (Singleton.class){
                if (instance  == null)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

枚举(num)

枚举方式很容易被大家给忽略掉了但这种方式我觉得是最简单且又友好的一种推荐创建单例的方式通过enum修饰Singleton单例类仅需定义一个INSTANCE然后在静态方法实例化方法getInstance中直接返回INSTANCE即可。

/**
 * 单例模式之枚举
 */
public enum Singleton {
    INSTANCE;
    public static Singleton getInstance(){
        return INSTANCE;
    }
}

总结

设计模式之单例模式看似挺简单其实还涉及了枚举enum、同步锁synchronized、JVM类加载机制、多线程volatile关键字的使用等Java的N个知识点。

本篇文章就到这里了希望能够给你带来帮助也希望您能够多多关注的更多内容!


相关文章

猜您喜欢

网友评论

Copyright 2020 www.Shellfishsoft.com 【贝软下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式