面试题—5种单例模式写法以及单线程和多线程下的区别

面试题—5种单例模式写法以及单线程和多线程下的区别闲来无事看之前的博客,发现单例模式只会写2中。所以再重新开一篇博客,将目前自己所能理解的几种单例模式全部总结下。______________________________________________________________________________________________________________________1、懒汉式(最基本的) 单线程版写单例模式(饿汉式)的步骤: 1):必须在该类中,自己先创建出一个对象。 2):私有化自身的…

大家好,又见面了,我是你们的朋友全栈君。

闲来无事看之前的博客,发现单例模式只会写2中。所以再重新开一篇博客,将目前自己所能理解的几种单例模式全部总结下。

___________________________________________________________________________________________________________

 

1、懒汉式(最基本的) 单线程版

写单例模式(饿汉式)的步骤:

      1):必须在该类中,自己先创建出一个对象。

      2):私有化自身的构造器,防止外界通过构造器创建新的对象。

      3):想外暴露一个公共的静态方法用于获取自身的对象

缺点:单线程是没问题的 但是多线程就会产生线程问题  下面会介绍多线程版本

//  懒汉式类初始化的,不会创建该对象,真正需要的时候才会加载(创建),天生线程不安全,需要解决线程安全问题,所有效率比较低
public class SingletonLazy {

    private SingletonLazy() {
        System.out.println(Thread.currentThread().getName());
    }

    private static SingletonLazy singletonLazy;

    public static SingletonLazy getInstance() {
        if (singletonLazy == null) {
            singletonLazy = new SingletonLazy();
        }
        return singletonLazy;
    }

    public static void main(String[] args) {

        SingletonLazy singletonLazy1 = SingletonLazy.getInstance();
        SingletonLazy singletonLazy2 = SingletonLazy.getInstance();
        System.out.println(singletonLazy1 == singletonLazy2);   // true
    }
}

多线程版本线程不安全(最简单的案例):

public class SingletonLazy {

    private SingletonLazy() {
        System.out.println(Thread.currentThread().getName());
    }

    private static SingletonLazy singletonLazy;

    public static SingletonLazy getInstance() {
        if (singletonLazy == null) {
            singletonLazy = new SingletonLazy();
        }
        return singletonLazy;
    }

    public static void main(String[] args) {
       
        for (int i = 0; i <= 500; i++) {
            new Thread(() -> {
                try {
                    getInstance();
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }, String.valueOf(i)).start();
        }
      
       
    }
}

2、饿汉式(最基本的)

 优点:线程天生安全  类在整个生命周期中只会被加载一次,因此该单例类只会创建一个实例,也就是说,线程每次都只能也必定只可以拿到这个唯一的对象
 缺点:类加载的时候就会加载 static 对象 如果暂时用不到呢  就会占用极大的内存
 



public class SingletonHungry {
//    会浪费内存
//    byte[] data1 = new byte[1024*1024];
//    byte[] data2 = new byte[1024*1024];

    private SingletonHungry() {
        System.out.println(Thread.currentThread().getName());
    }

    //小知识: 当使用static 修饰时 会存档在 JVM的方法区  JVM垃圾回收机制 不会进行回收
    private static final SingletonHungry singletonDemo = new SingletonHungry();


    private static SingletonHungry getInstance() {
        return singletonDemo;
    }

    public static void main(String[] args) {
        
        SingletonHungry singletonDemo = getInstance();
        SingletonHungry singletonDemo2 = getInstance();

        System.out.println(singletonDemo == singletonDemo2);  // true
    }
}

 

3、枚举

枚举是一个特殊的类
内部将构造器进行私有化,因此不能通过New 的方式进行创建

有兴趣可以测试下 ,我这比较简单

public enum  EnumSingleton {
    INSTANCE;
    public EnumSingleton getInstance(){
        return INSTANCE;
    }
}

4、静态内部类

public class SingletonStatic {
    private SingletonStatic() {}
    public static class  SingletonClassInstance{
        private static final SingletonStatic single = new SingletonStatic();
    }
    public static SingletonStatic getInstance(){
        return SingletonClassInstance.single;
    }

    public static void main(String[] args) {
        SingletonStatic singleton1 = SingletonStatic.getInstance();
        SingletonStatic singleton2 = SingletonStatic.getInstance();

        System.out.println(singleton1 ==singleton2);
    }
}

5、DCL(双重检验锁)

在  new MultiSingletonDCL();时候由于会发生指令重排序  可能会出现问题 因此加上关键字   volatile

// 1. 分配内存空间
// 2. 执行构造方法,初始化对象
// 3. 把这个对象指向这个空间
// 双锁机制的出现是为了解决前面同步问题和性能问题

public class SingletonDCL {

    private volatile static MultiSingletonDCL multiSingletonDCL;
    private SingletonDCL() {
        System.out.println(Thread.currentThread().getName());

    }

    private static SingletonDCL getInstance() {
        if (singletonLazyDCL == null){
            synchronized (SingletonDCL.class){
                if (singletonLazyDCL == null){
                        
                    singletonLazyDCL = new SingletonDCL();
                }
            }
        }
        return singletonLazyDCL;
    }
    public static void main(String[] args) {

        SingletonDCL instance = SingletonDCL.getInstance();
        SingletonDCL instance2 = SingletonDCL.getInstance();
        System.out.println(instance == instance2);
    }
}

本文如有问题,希望大佬指正。不胜感激。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/147130.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 分水岭算法 matlab实现

    分水岭算法 matlab实现背景     做图像分割的时候用到了,就学习了一下大概思想     把图像中的像素大小理解成山地的海拔,向山地灌水,海拔低的地方会积水,这些地方称之为谷底。随着水位上升,不同谷底的水会相遇,相遇的地方就是分水岭。    &nbs

    2022年6月17日
    24
  • Volatile详解,太详细了「建议收藏」

    Volatile详解,太详细了「建议收藏」Volatile可能是面试里面必问的一个话题吧,对他的认知很多朋友也仅限于会用阶段,今天我们换个角度去看看。先来跟着丙丙来看一段demo的代码:你会发现,永远都不会输出有点东西这一段代码,按道理线

    2022年7月4日
    24
  • 【机器学习笔记】——感知机(Perceptron)

    【机器学习笔记】——感知机(Perceptron)目录 1 感知机 Perceptron 1 1 定义 1 2 几何解释 1 3 学习策略 1 4 算法 1 4 1 原始形式 1 4 2 对偶形式 2 算法实现 2 1 实现原始形式算法 2 2 实现对偶形式算法 2 3sklearn 练习 自定义数据二分类 2 4 对比练习 鸢尾花数据分类鸢 2 4 1 尾花数据集 2 4 2 数据预处理与特征选择 2 4 3 对比手写模型与 sklearn 效果 2 4 3 1 准备

    2025年10月21日
    4
  • VC++常用功能开发「建议收藏」

    VC++常用功能开发「建议收藏」系列文章目录第一章:VC++ini配置文件封装类源代码第二章:VC++实现二维码(显示+保存图片)功能源代码第三章:VC++调节系统音量(与任务栏音量同步)源代码提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录系列文章目录 前言 一、pandas是什么? 二、使用步骤 1.引入库 2.读入数据 总结前言提示:这里可以添加本文要记录的大概内容:例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启..

    2022年5月2日
    30
  • html5是什么意思,HTML5是什么 HTML5是什么意思?

    html5是什么意思,HTML5是什么 HTML5是什么意思?随着Windows8正式版发布的脚步近在咫尺,近来关于Win8、IE10、HTML5的新闻逐渐增多,很多朋友对于Win8系统以及IE10浏览器都比较了解,但对于HTML5是什么还真有不少朋友不清楚,很多媒体网站在报道IE10浏览器支持最新html5的时候,不少朋友还是一头雾水,以下电脑百事网小编为大家简单介绍下HTML5是什么。HTML5是什么HTML5是什么意思专业的说,HTML5是用于取代1…

    2025年7月11日
    4
  • 操作系统核心原理之内存管理思维导图

    操作系统的两个角色分别是魔术师和管理者,在管理者这个角色中,除了CPU之外,内存是操作系统要管理的另外一个重要资源。内存管理需要达到两个目标:一是地址保护,即一个程序不能访问另一个程序的地址空间。二是

    2021年12月19日
    52

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号