基于Java利用static实现单例模式

作者:灵剑山真人 时间:2021-12-20 06:07:32 

一、之前旧的写法

class Singleton{
    private Singleton() {}
    private static Singleton instance = null;
    public synchronized static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
}

就利用Sington.getInstace就可以了,获得的是同一个实例。

上面那个代码有两个优点:

  • 懒加载,把在堆创建实例这个行为延迟到类的使用时。

  • 锁效果,防止生成多个实例,因为synchronized修饰这个static方法,所以相当于给这个方法加上了一个类锁🔒。

二、static代码块的效果

先来看一段代码:

 

class StaticClass{
    private static int a = 1;
    static{
        System.out.println("语句1");
        System.out.println("语句2");
    }
    static{
        System.out.println("语句3");
        System.out.println("语句4");
    }
}

当在多个线程同时触发类的初始化过程的时候(在初始化过程,类的static变量会被赋值为JVM默认值并且static代码块会被执行),为什么static不会被多次执行?因为有可能两个线程同时检测到类还没被初始化,然后都执行static代码块,结果就把语句1234多打印了,为什么上述情况不会发生。

Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Class.forName("StaticClass");//这一行触发类的初始化导致静态代码块执行
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        });
        thread1.start();
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Class.forName("StaticClass");//同样
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        });
        thread2.start();

结果如下:

语句1
语句2
语句3
语句4

有一段英文对其进行了解释:

static initialization block can be triggered from multiple parallel threads (when the loading of the class happens in the first time), Java runtime guarantees that it will be executed only once and in thread-safe manner + when we have more than 1 static block - it guarantees the sequential execution of the blocks, 也就是说,java runtime帮我们做了两件事:

  • 在并行线程中,都出现了第一次初始化类的情况,保证类的初始化只执行一次。

  • 保证static代码块的顺序执行

三、单例的另一种写法

有了对static的知识的了解之后,我们可以写出这样的单例模式:

class Singleton{
    private Singleton() {}
    private static class NestedClass{
       static Singleton instance = new Singleton();//这条赋值语句会在初始化时才运行
    }
    public static Singleton getInstance() {
        return NestedClass.instance;
    }
}
  • 懒加载,因为static语句会在初始化时才赋值运行,达到了懒加载的效果。

  • 锁🔒的效果由Java runtime保证,虚拟机帮我们保证static语句在初始化时只会执行一次。

四、总结

如果不知道static的基础知识和虚拟机类加载的知识,我可能并不会知道这一种方法。理论永远先行于技术,要学好理论才能从根本上提升自己。

来源:https://www.cnblogs.com/--here--gold--you--want/p/15779594.html

标签:Java,static,单例模式
0
投稿

猜你喜欢

  • Mac OS下为Android Studio编译FFmpeg解码库的详细教程

    2023-06-30 02:37:54
  • Java泛型映射不同的值类型详解及实例代码

    2023-07-29 00:20:52
  • Java手动实现Redis的LRU缓存机制

    2023-07-31 12:51:30
  • IDEA解决maven包冲突easypoi NoClassDefFoundError的问题

    2023-10-16 14:51:38
  • java中ArrayList和LinkedList的区别详解

    2022-09-05 11:13:48
  • jsp如何获取Session中的值

    2023-07-01 05:59:28
  • Mybatis整合达梦数据库的完整步骤记录

    2023-11-23 07:15:37
  • Java 设计模式中的命令模式详情

    2023-11-15 23:25:33
  • Java双冒号(::)运算符使用详解

    2022-03-31 11:18:17
  • 基于Java GUI 事件处理方式

    2023-11-25 13:08:55
  • mybatis-plus生成mapper扩展文件的方法

    2023-08-10 07:29:05
  • java自定义ClassLoader加载指定的class文件操作

    2022-03-16 16:19:07
  • springboot使用单元测试实战

    2023-05-17 11:55:29
  • 详解Java注解的实现与使用方法

    2023-10-31 12:33:20
  • Spring注解@Configuration与@Bean注册组件的使用详解

    2022-09-13 01:52:56
  • SpringBoot整合Redis之编写RedisConfig

    2023-08-29 02:35:57
  • Java 守护线程_动力节点Java学院整理

    2023-11-28 07:51:14
  • Java 如何实现一个http服务器

    2022-03-27 05:40:04
  • java面试题之try中含return语句时代码的执行顺序详解

    2023-11-24 07:34:16
  • Spring Boot thymeleaf模板引擎的使用详解

    2022-07-27 07:42:54
  • asp之家 软件编程 m.aspxhome.com