• 第一季:2单例设计模式【Java面试题】


    前言


    2022 9/29 22:59

    路漫漫其修远兮,吾将上下而求索


    本文是根据尚硅谷学习所做笔记

    仅供学习交流使用,转载注明出处


    推荐

    【尚硅谷经典Java面试题第一季(java面试精讲)-哔哩哔哩】

    尚硅谷经典Java面试题一二三季

    尚硅谷经典Java面试题(第1季)

    第一季:2单例设计模式

    推荐:
    单例模式【Java设计模式】
    设计模式【java提高】

    题目

    编程题:写一个Singleton实例

    什么是Singleton ?

    • Singleton:在Java中即指单例设计模式,它是软件开发中最常用的设计模式之一
    • 单:唯一
    • 例:实例
      0103
    • 单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。
    • 例如:代表JVM运行环境的RunTime类

    要点

    • 一是某个类只能有一个实例;
      ◆构造器私有化
    • 二是它必须自行创建这个实例;
      ◆含有一个该类的静态变量来保存这个唯一的实例
    • 三是它必须自行向整个系统提供这个实例;
      ◆对外提供获取该实例对象的方式:
      (1)直接暴露(2)用静态变量的get方法获取

    0218

    几种常见形式

    • 饿汉式∶直接创建对象,不存在线程安全问题
      • 直接实例化饿汉式(简洁直观)
      • 枚举式(最简洁)
      • 静态代码块饿汉式(适合复杂实例化)
    • 懒汉式:延迟创建对象
      • 线程不安全(适用于单线程)
      • 线程安全(适用于多线程)
      • 静态内部类形式(适用于多线程)

    0300

    实现

    饿汉式

    直接实例化饿汉式(简洁直观)

    package singleton2;
    
    /**
     * 饿汉式
     *  直接创建实例对象,不管你是否需要对象都会创建
     * (1)构造器私有化
     * (2)自行创建,并且用静态变量保存
     * (3)向外提供这个实例
     * (4)强调这是个单例,我们可以使用final修改
     */
    public class Singleton1 {
        public static final Singleton1 INSTANCE=new Singleton1();
        private Singleton1(){
    
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    枚举式(最简洁)

    package singleton2;
    
    /**
     * 枚举类型,表示给类型的对象是有限的几个
     * 我们可以限定为一个,就成为了单例了
     */
    public enum Singleton2 {
        INSTANCE
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    静态代码块饿汉式(适合复杂实例化)

    package singleton2;
    
    import java.io.IOException;
    import java.util.Properties;
    
    public class Singleton3 {
        public static final Singleton3 INSTANCE;
        private String info;
        static {
            try {
                Properties pro=new Properties();
                //用类加载器加载src下的配置文件
                pro.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties"));
                INSTANCE=new Singleton3(pro.getProperty("info"));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        private Singleton3(String info){
            this.info=info;
        }
    
        public String getInfo() {
            return info;
        }
    
        public void setInfo(String info) {
            this.info = info;
        }
    
        @Override
        public String toString() {
            return "Singleton3{" +
                    "info='" + info + '\'' +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    single.properties

    #key=value
    info=atguigu
    
    • 1
    • 2

    测试

    package singleton2;
    
    import org.junit.Test;
    
    public class TestSingletonEHan {
    
        @Test
        public void testSingleton1(){
            Singleton1 s=Singleton1.INSTANCE;
            System.out.println(s);//singleton2.Singleton1@1b9e1916
        }
    
        @Test
        public void testSingleton2(){
            Singleton2 s=Singleton2.INSTANCE;
            System.out.println(s);//INSTANCE
        }
    
        @Test
        public void testSingleton3(){
            Singleton3 s=Singleton3.INSTANCE;
            System.out.println(s);//Singleton3{info='atguigu'}
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    懒汉式

    线程不安全(适用于单线程)

    package singleton2;
    
    /**
     * 懒汉式
     *
     * (1)构造器私有化
     * (2)用一个静态变量保存这个唯一的实例
     * (3)提供一个静态方法,获取这个实例对象
     *
     */
    public class Singleton4 {
        private static Singleton4 instance;
        private Singleton4(){
    
        }
        public static Singleton4 getInstance(){
            if (instance==null){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                instance=new Singleton4();
            }
            return instance;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    线程安全(适用于多线程)

    package singleton2;
    
    /**
     * 懒汉式
     *
     * (1)构造器私有化
     * (2)用一个静态变量保存这个唯一的实例
     * (3)提供一个静态方法,获取这个实例对象
     *
     */
    public class Singleton5 {
        private volatile static Singleton5 instance;
        private Singleton5(){
    
        }
        public static Singleton5 getInstance(){
            if (instance==null) {
                synchronized (Singleton5.class) {
                    if (instance==null){
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        instance=new Singleton5();
                    }
                }
            }
            return instance;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    静态内部类形式(适用于多线程)

    package singleton2;
    
    /**
     * 在内部类被加载和初始化时,才创建INSTANCE
     * 静态类不会自动随着外部类的加载和初始化而初始化的,它是要单独去加载和初始化的。
     * 因为是在内部类加载和初始化时,创建的,因此是线程安全的
     */
    public class Singleton6 {
        private Singleton6(){
    
        }
        private static class Inner{
            private static final Singleton6 INSTANCE =new Singleton6();
        }
        public static Singleton6 getInstance(){
            return Inner.INSTANCE;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    测试

    package singleton2;
    
    import org.junit.Test;
    
    import java.util.concurrent.*;
    
    public class TestSingletonLanHan {
    
        @Test
        public void testSingleton4() throws ExecutionException, InterruptedException {
            /*
            Singleton4 s1=Singleton4.getInstance();
            Singleton4 s2=Singleton4.getInstance();
            System.out.println(s1==s2);//true
            System.out.println(s1);//singleton2.Singleton4@1b9e1916
            System.out.println(s2);//singleton2.Singleton4@1b9e1916
            */
    
            Callable<Singleton4> c=new Callable<Singleton4>() {
                @Override
                public Singleton4 call() throws Exception {
                    return Singleton4.getInstance();
                }
            };
            ExecutorService es= Executors.newFixedThreadPool(2);
            Future<Singleton4> f1 = es.submit(c);
            Future<Singleton4> f2 = es.submit(c);
    
            Singleton4 s1 = f1.get();
            Singleton4 s2 = f2.get();
    
            System.out.println(s1==s2);//false
            System.out.println(s1);//singleton2.Singleton4@3b764bce
            System.out.println(s2);//singleton2.Singleton4@759ebb3d
    
            es.shutdown();
        }
    
        @Test
        public void testSingleton5() throws ExecutionException, InterruptedException {
            Callable<Singleton5> c=new Callable<Singleton5>() {
                @Override
                public Singleton5 call() throws Exception {
                    return Singleton5.getInstance();
                }
            };
            ExecutorService es= Executors.newFixedThreadPool(2);
            Future<Singleton5> f1 = es.submit(c);
            Future<Singleton5> f2 = es.submit(c);
    
            Singleton5 s1 = f1.get();
            Singleton5 s2 = f2.get();
    
            System.out.println(s1==s2);//true
            System.out.println(s1);//singleton2.Singleton5@3b764bce
            System.out.println(s2);//singleton2.Singleton5@3b764bce
    
            es.shutdown();
        }
    
        @Test
        public void testSingleton6(){
            Singleton6 s=Singleton6.getInstance();
            System.out.println(s);//singleton2.Singleton6@1b9e1916
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    最后


    2022 9/29 23:49


    p2


    Markdown 5062 字数 364 行数
    HTML 4532 字数 249 段落


  • 相关阅读:
    LeetCode 周赛 347(2023/05/28)二维空间上的 LIS 最长递增子序列问题
    【web前端期末大作业】基于HTML+CSS+JavaScript实现代理商销售管理系统后台(8页)
    MLOps最全的资料合集:书籍、课程与博文
    微服务从代码到k8s部署应有尽有系列(十四、部署环境搭建)
    vulnhub靶场之HACK ME PLEASE
    21.4 Python 使用GeoIP2地图定位
    web3.0 nft 是什么? nft的意义是什么?
    乌班图22.04 kubeadm简单搭建k8s集群
    C#文件拷贝工具
    接口自动化测试框架postman tests常用方法
  • 原文地址:https://blog.csdn.net/qq_51625007/article/details/127115513