利用static来实现单例模式

Python微信订餐小程序课程视频

https://edu.csdn.net/course/detail/36074

Python实战量化交易理财系统

https://edu.csdn.net/course/detail/35475

一:之前旧的写法

复制代码

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

就利用Sington.getInstace就可以了,获得的是同一个实例。上面那个代码有两个优点:

  1. 懒加载,把在堆创建实例这个行为延迟到类的使用时。
  2. 锁效果,防止生成多个实例,因为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帮我们做了两件事:

  1. 并行线程中,都出现了第一次初始化类的情况,保证类的初始化只执行一次。
  2. 保证static代码块的顺序执行

三:单例的另一种写法

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

复制代码

class Singleton{
 private Singleton() {}
 private static class NestedClass{
 static Singleton instance = new Singleton();//这条赋值语句会在**初始化**时才运行
 }
 public static Singleton getInstance() {
 return NestedClass.instance;
 }
}
  1. 懒加载,因为static语句会在初始化时才赋值运行,达到了懒加载的效果。
  2. 锁🔒的效果由Java runtime保证,虚拟机帮我们保证static语句在初始化时只会执行一次。

四:总结

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

本博文站在以下这位巨人的肩膀上:https://www.linkedin.com/pulse/static-variables-methods-java-where-jvm-stores-them-kotlin-malisciuc

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值