当前位置: 首页 > news >正文

JVM(二)------ 类加载、初始化与单例模式的联系

首先我们要知道,单例模式有饿汉式和懒汉式两种

(一)饿汉单例

先说饿汉式:

public class SingletonEager {// ① 类加载时立即创建实例private static final SingletonEager instance = new SingletonEager();// ② 私有构造函数,外部无法 newprivate SingletonEager() {System.out.println("构造函数被调用");}// ③ 提供全局访问点public static SingletonEager getInstance() {return instance;}
}

饿汉单例模式关键就是:类加载时就创建对象实例 + 每次访问都返回同一个对象实例

①类加载时就创建对象实例

前者好保证,就是代码中的①,创建一个static final修饰的对象实例,那么这个类在加载时就会创建对象实例,在准备阶段由于这是一个new的对象,所以赋默认值:null;

②每次访问都返回同一个对象实例

那么对于后者,就有两个维度:

  1. 首先要保证外部访问时对象已经创建好,不能将创建对象的权力交给外部(构造函数私有)
  2. 其次就是每次请求都返回之前创建好的对象的引用

对于第2点,流程是这样的:

  1. 暴露一个getInstance()函数,外部想要获得对象只能通过这种手段;
  2. 当外部调用时,类才真正执行初始化(第一次调用静态方法),static final SingletonEager instance = new SingletonEager();的过程中,jvm会保证类的初始化(<clinit>(静态初始化))是线程安全并且只进行一次的,所以这个对象只会被创建一个;
  3. 最后,return instance;返回的都是这同一个对象的引用,保证了单例

这就是饿汉单例;

(二)懒汉单例

顾名思义,就是使用到的时候再创建,饿汉单例由于一开始就创建并赋值,所以类加载的时候就会赋默认值,但是饿汉单例只是声明,所以类加载的时候就不会创建这个对象;

public class SingletonLazy {private static SingletonLazy instance; // 还没创建private SingletonLazy() {System.out.println("Lazy 构造函数被调用");}public static SingletonLazy getInstance() {if (instance == null) { // 第一次使用时才创建instance = new SingletonLazy();}return instance;}
}

而等到外部调用静态方法时,那么执行类的初始化,但是由于懒汉单例只是声明对象没有要赋值,所以jvm的执行<clinit>并不包含对象的赋值,因此就需要我们手动判断对象只创建一个(但是!!! 先判断后执行,这个动作不是原子性的,所以不是线程安全的)。

解决方法:

1.加synchronized锁:安全但是效率低

public class SingletonLazySafe {private static SingletonLazySafe instance;private SingletonLazySafe() {System.out.println("SingletonLazySafe 构造函数被调用");}public static synchronized SingletonLazySafe getInstance() {if (instance == null) {instance = new SingletonLazySafe();}return instance;}
}

(三)懒汉单例----线程安全

使用静态内部类的方式,为什么??? 想一下懒汉单例为什么线程安全?? 因为其静态变量的赋值借助了JVM在进行类初始化(真正初始化静态变量,静态方法)的时候,线程安全是由JVM保证的,所以我们可以通过第二种:将对象创建放在静态内部类中,那么这个内部类在类加载时不会初始化,只在调用到类的静态方法时被初始化,原理有些类似于静态变量:

由于JVM调用<clinit>只会执行一次且是线程安全的,那么这个实例只有一个并且创建过程中线程安全。

public class SingletonInner {private SingletonInner() {System.out.println("SingletonInner 构造函数被调用");}// 静态内部类,只有在第一次调用 getInstance() 时才加载private static class Holder {private static final SingletonInner INSTANCE = new SingletonInner();}public static SingletonInner getInstance() {return Holder.INSTANCE;}
}

http://www.dtcms.com/a/589715.html

相关文章:

  • 做【秒开】的程序:WPF / WinForm / WinUI3 / Electron
  • 小白零基础教程:安装 Conda + VSCode 配置 Python 开发环境
  • Word技巧:制作可勾选的复选框并自定义选中符号
  • 做彩票网站违法吗最专业的做网站公司
  • 淘宝刷单网站建设未来做哪个网站致富
  • php婚庆网站贵州建设官方网站
  • 将你的旧手机变成监控摄像头(Python + OpenCV)
  • 推广网站2024网络策划专员
  • 如何利用模板建站增城网站公司电话
  • week9
  • 网站上线除了备案还需要什么扬州广陵区城乡建设局网站
  • 原生CSS讲解
  • Lit.js 入门介绍:与 React 的对比
  • 【Gateway】服务调用和网关配置攻略
  • 万网域名注册后怎么样做网站做网站必须原创吗
  • 青岛企业网站建设wordpress乱码
  • 《Redis应用实例》Java实现(27):定长队列和淘汰队列
  • 做网站服务器怎么用怎样创建行业门户网站
  • net core开发跨平台的桌面应用,如上位机很实用
  • python+playwright:如何解决某个页面不稳定的出现不影响ui自动化执行
  • Redis 使用场景
  • 针对动态连接场景的验证环境搭建思路
  • 网页制作与网站建设答案专业建设汇报ppt
  • 机器学习21:可解释机器学习(Explainable Machine Learning)(上)
  • 深圳开发网站建设哪家好软件仓库
  • 潍坊网站建设团队微信开放平台小程序
  • Vue 项目实战《尚医通》,根据等级和地区获取医院信息,笔记14
  • C语言关键字详解
  • SmartResume简历信息抽取框架深度解析
  • 2.4 使用 PyTorch / TensorFlow 实现文本分类