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

在自己网站做支付可以吗直销怎么做才最快成功

在自己网站做支付可以吗,直销怎么做才最快成功,硬件开发工程师笔试题,企业微网站建设目录 背景前置知识类加载运行全过程 单例模式的实现方式一、饿汉式基本介绍源码分析 二、懒汉式基本介绍源码分析改进 三、懒汉式单例终极解决方案(静态内部类)(推荐使用方案)基本介绍源码分析 感谢 背景 最近学习了JVM之后&…

目录

  • 背景
  • 前置知识
    • 类加载运行全过程
  • 单例模式的实现方式
    • 一、饿汉式
      • 基本介绍
      • 源码
      • 分析
    • 二、懒汉式
      • 基本介绍
      • 源码
      • 分析
      • 改进
    • 三、懒汉式单例终极解决方案(静态内部类)(推荐使用方案)
      • 基本介绍
      • 源码
      • 分析
  • 感谢

背景

最近学习了JVM之后,总感觉知识掌握不够深,所以想通过分析经典的【懒汉式单例】来加深一下理解。(主要是【静态内部类】实现单例的方式)。
如果小白想理解单例的话,也能看我这篇文章。我也通过了【前置知识】跟【普通懒汉式】、【双检锁懒汉】、【静态内部类】懒汉给大家分析了一下他们的线程安全性。但是,我这边没有完整的演进【懒汉式单例】历程。所以,会缺少思维上的递进。不过,我在最后的【感谢】名单里,提供了一个完整的【懒汉式单例演进】的链接,建议可以结合这个文章一起学习。

前置知识

类加载运行全过程

当我们用java命令运行某个类的main函数启动程序时,首先需要通过类加载器把主类加载到JVM。

package com.tuling.jvm;public class Math {public static final int initData = 666;public static User user = new User();public int compute() {  //一个方法对应一块栈帧内存区域int a = 1;int b = 2;int c = (a + b) * 10;return c;}public static void main(String[] args) {Math math = new Math();math.compute();}
}

通过Java命令执行代码的大体流程如下:
在这里插入图片描述
其中loadClass的类加载过程有如下几步:
加载 >> 验证 >> 准备 >> 解析 >> 初始化 >> 使用 >> 卸载

  • 加载:在硬盘上查找并通过IO读入字节码文件,使用到类时才会加载,例如调用类的main()方法,new对象等等,在加载阶段会在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
  • 验证:校验字节码文件的正确性
  • 准备:给类的静态变量分配内存,并赋予默认值
  • 解析:将符号引用替换为直接引用,该阶段会把一些静态方法(符号引用,比如main()方法)替换为指向数据所存内存的指针或句柄等(直接引用),这是所谓的静态链接过程(类加载期间完成),动态链接是在程序运行期间完成的将符号引用替换为直接引用,下节课会讲到动态链接
  • 初始化:对类的静态变量初始化为指定的值,执行静态代码块
    在这里插入图片描述

总结一下,上面说的加载 >> 验证 >> 准备 >> 解析 >> 初始化过程是由JVM帮我们进行的,所以,对我们程序员来说,【天生】就具备线程安全性(这个由JVM帮我们保证,无需我们关心)。

单例模式的实现方式

单例模式,是我们Java中很常见的一个设计模式。所以有这么一种说法:遇事不决,单例解决。
Java单例通常有2种,分别为:饿汉式、懒汉式

一、饿汉式

基本介绍

饿汉式(Eager Initialization,急切的初始化),在类加载时就创建单例实例,并在需要时直接返回该实例。这种方式的实现是线程安全的,因为在类加载过程中实例已经创建好了。

源码

public class SingletonTest {private static final SingletonTest me = new SingletonTest();public static SingletonTest me() {return me;}public static void main(String[] args) {System.out.println(SingletonTest.me());System.out.println(SingletonTest.me());System.out.println(SingletonTest.me());}
//    系统输出如下:
//    org.tuling.juc.singleton.SingletonTest@12a3a380
//    org.tuling.juc.singleton.SingletonTest@12a3a380
//    org.tuling.juc.singleton.SingletonTest@12a3a380
}

分析

因为单例对象SingletonTest 是静态成员变量,所以,在JVM类加载过程中==(加载-》验证-》准备-》解析-》初始化)==的【解析】阶段已经被JVM初始化了,所以,由JVM保证了线程安全性。

二、懒汉式

基本介绍

懒汉式(Lazy Initialization),在首次调用时创建单例实例,存在线程安全问题。如果多个线程同时进入判断条件,可能会创建多个实例。

源码

public class SingletonTest {private static SingletonTest me;public static SingletonTest me() {if(me == null) {me = new SingletonTest();}return me;}public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(()->{System.out.println(SingletonTest.me());}).start();}}
}

输出结果如下
在这里插入图片描述

分析

为什么上面这段代码不是线程安全的呢?我们举一个极端的例子,如下图所示:
在这里插入图片描述
在没有锁机制的存在情况下,多线程环境里面可能会出现上述的并发执行情况。在线程1判断完me == null之后,即将开始执行new之前,线程2也刚好在判断me == null,这是因为线程1还没有执行new操作,所以线程2判断肯定是null的,于是也开始new。这就是线程安全问题所在。
(PS:小白们一定要理解上面这个图。虽然很简单,但是说它是你们迈向,或者培养【并发意识】的启蒙都不为过。)

改进

为了解决上面的问题,大牛们进行了改进,使用了【双检锁+volatile】机制,【双检锁】,即:双重检查锁。代码如下:

public class SingletonTest {private static volatile SingletonTest me;public static SingletonTest me() {if(me == null) {synchronized (SingletonTest.class) {if (me == null) {me = new SingletonTest();}}}return me;}
}

上面的改进,关键点如下:

  1. 使用了volatile关键字修饰单例对象me
  2. 在获取单例对象的时候,判断了两次if(me == null)
  3. 第二次判断if(me == null)之前,先加了锁

第二、三点我就不说了,大家可以看看最下面【感谢】的友链。这里重点说说第一点。
估计小白会很难理解,为什么一定要volatile关键字修饰,不用可以吗?答案是:不可以。因为,volatile能禁止重排序。什么是【重排序呢】?说的简单点,就是JVM,甚至是CPU为了性能,可能会在不改变语义的情况下修改我们的代码执行顺序。比如,当我们new SingletonTest()的时候,你以为只有一步操作,实际上,它有3步,如下:

memory = allocate(); // 1.分配对象内存空间
instance(memory); // 2.初始化对象
instance = memory; // 3.设置instance指向刚分配的内存地址,此时instance!=null

但事实上,经过重排序之后可能会变成下面的执行顺序:

memory = allocate(); // 1.分配对象内存空间
instance = memory; // 3.设置instance指向刚分配的内存地址,此时instance!=null
instance(memory); // 2.初始化对象

然后大家再用上面的【并发启蒙】意识,自己画个图看下,还能线程安全吗?
所以,需要使用volatile关键字,告诉底层JVM或者CPU,不要帮我重排序这个对象!于是就避免了上面的并发线程安全问题了。

三、懒汉式单例终极解决方案(静态内部类)(推荐使用方案)

基本介绍

这里通过利用JVM类加载【天生线程安全】的特性,来帮助实现【懒汉式】的单例。如何做到呢?答案是【静态内部类】。

源码

public class SingletonTest {/** 单例对象,可以直接调用配置属性  */private static class Holder {private static SingletonTest me = new SingletonTest();}public static SingletonTest me() {return Holder.me;}public static void main(String[] args) {int threadCount = 10000;for (int i = 0; i < threadCount; i++) {new Thread(()->{System.out.println(SingletonTest.me());}).start();}}
}

上面的代码,新建了1W个线程来调用单例,我们发现,结果都是一样,同一个对象。
在这里插入图片描述

分析

为什么上面,通过静态内部类能保证线程安全性呢?这个我们在【前置知识】已经说过了,是由JVM保证了线程安全性。
在这里插入图片描述
如上图所示,只有当我们使用了SingletonTest.me()的时候,才会去开始加载Holder静态内部类,这就是它实现【懒汉式】的原因(延迟加载)。

感谢

感谢【作者:weixin_47196090】的深度好文,《懒汉式单例演进到DCL懒汉式 深度全面解析》

http://www.hengruixuexiao.com/news/33698.html

相关文章:

  • 做核酸收费seo如何快速排名百度首页
  • 做农宿的网站昆明seo外包
  • 做的网站必须备案自己的网站怎么在百度上面推广
  • 商城网站如何提高收录郑州seo
  • 网站logo优化免费卖货平台
  • 电子商务网站建设 课后答案友情链接分析
  • 如何网站做外贸生意印度疫情最新消息
  • eclipse做企业网站汽油价格最新调整最新消息
  • 合肥餐饮网站建设seo效果最好的是
  • 网站和新媒体建设审批制度单页站好做seo吗
  • 宝应网站建设二级子域名ip地址查询
  • 收费下载的wordpress网站做网站好的网站建设公司
  • 公众号免费模板seo高效优化
  • 网站漂浮广告怎么做国内免费发布产品的平台
  • 网站做销售是斤么工作网络营销的真实案例分析
  • 淘宝网站怎么做的好坏创意设计
  • wordpress建站多用户搜索引擎调词平台
  • 盗取dede系统做的网站模板拓客引流推广
  • 衡水网站建设格公司强化防疫指导
  • 深圳制作网站软件搜索网站排行榜
  • 加强局网站建设it培训班出来工作有人要么
  • 万网域名管理网站淘宝搜索关键词排名查询工具
  • 网站备案时间有效期肇庆seo外包公司
  • 国际品牌的ui设计公司百度整站优化
  • 开县做网站夸克搜索网页版
  • 发卡网站搭建windows7系统优化工具
  • 如果熊掌号做的不好会不会影响网站线上卖货平台有哪些
  • 百度如何把网站做链接地址网络营销的推广方式都有哪些
  • phpwind 做企业网站网站服务器多少钱一年
  • 网站建设毕业设计中期检查中国最新军事新闻最新消息