Java核心技术36讲 杨晓峰

模块四 Java性能基础

第34讲 | 有人说“Lambda能让Java程序慢30倍”,你怎么看

如果 Stream 使用不当,会让你的代码慢 5 倍

基准测试框架 JMH

JMH上手步骤

JMH样例代码

JMH 是由 Hotspot JVM 团队专家开发的,除了支持完整的基准测试过程,包括预热、运行、统计和报告等,还支持 Java 和其他 JVM 语言。更重要的是,它针对 Hotspot JVM 提供了各种特性,以保证基准测试的正确性,整体准确性大大优于其他框架,并且,JMH 还提供了用近乎白盒的方式进行 Profiling 等工作的能力。

使用 JMH 也非常简单,你可以直接将其依赖加入Maven工程

mvn archetype:generate \
      	-DinteractiveMode=false \
      	-DarchetypeGroupId=org.openjdk.jmh \
          -DarchetypeArtifactId=jmh-java-benchmark-archetype \
      	-DgroupId=org.sample \
      	-DartifactId=test \
      	-Dversion=1.0

一课一练

我们在项目中需要评估系统的容量,以计划和保证其业务支撑能力,谈谈你的思路是怎么样的?常用手段有哪些?

第35讲 | JVM优化Java代码时都做了什么?

模块四 Java性能基础

JVM 在对代码执行的优化可分为运行时(runtime)优化和即时编译器(JIT)优化。

运行时优化主要是解释执行和动态编译通用的一些机制,比如说锁机制(如偏斜锁)、内存分配机制(如 TLAB)等。除此之外,还有一些专门用于优化解释执行效率的,比如说模版解释器、内联缓存(inline cache,用于优化虚方法调用的动态绑定)。

JVM 的即时编译器优化是指将热点代码以方法为单位转换成机器码,直接运行在底层硬件之上。它采用了多种优化方式,包括静态编译器可以使用的如方法内联、逃逸分析,也包括基于程序运行 profile 的投机性优化(speculative/optimistic optimization)。这个怎么理解呢?比如我有一条 instanceof 指令,在编译之前的执行过程中,测试对象的类一直是同一个,那么即时编译器可以假设编译之后的执行过程中还会是这一个类,并且根据这个类直接返回 instanceof 的结果。如果出现了其他类,那么就抛弃这段编译后的机器码,并且切换回解释执行。

一课一练

如何程序化验证 final 关键字是否会影响性能?

第36讲 | 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?

第36讲 | 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?

模块5 Java应用开发扩展 (4讲)

MySQL 支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景

mysql(innodb)的可重复读隔离级别下,为什么可以认为不会出现幻像读呢?

从技术角度实现,mysq用mvcc做了snapshot,如果是locking read文档明确指出了会做区间锁定

乐观锁 悲观锁 脏读 幻读 不可重复读 CAS MVCC 隔离级别 锁队列 2PC TCC

一课一练

从架构设计的角度,可以将 MyBatis 分为哪几层?每层都有哪些主要模块?

mybatis架构自下而上分为基础支撑层、数据处理层、API接口层这三层。

基础支撑层,主要是用来做连接管理、事务管理、配置加载、缓存管理等最基础组件,为上层提供最基础的支撑。

数据处理层,主要是用来做参数映射、sql解析、sql执行、结果映射等处理,可以理解为请求到达,完成一次数据库操作的流程。

API接口层,主要对外提供API,提供诸如数据的增删改查、获取配置等接口。

第37讲 | 谈谈Spring Bean的生命周期和作用域?

第37讲 | 谈谈Spring Bean的生命周期和作用域?

模块5 Java应用开发扩展 (4讲)

谈谈 Spring Bean 的生命周期和作用域?

Spring Bean 生命周期比较复杂,可以分为创建和销毁两个过程。

首先,创建 Bean 会经过一系列的步骤,主要包括:

实例化 Bean 对象。

设置 Bean 属性。

如果我们通过各种 Aware 接口声明了依赖关系,则会注入 Bean 对容器基础设施层面的依赖。具体包括 BeanNameAware、BeanFactoryAware 和 ApplicationContextAware,分别会注入 Bean ID、Bean Factory 或者 ApplicationContext。

调用 BeanPostProcessor 的前置初始化方法 postProcessBeforeInitialization。

如果实现了 InitializingBean 接口,则会调用 afterPropertiesSet 方法。

调用 Bean 自身定义的 init 方法。

调用 BeanPostProcessor 的后置初始化方法 postProcessAfterInitialization。

创建过程完毕。

第二,Spring Bean 的销毁过程会依次调用 DisposableBean 的 destroy 方法和 Bean 自身定制的 destroy 方法。

广义上的 Spring 已经成为了一个庞大的生态系统,例如:

Spring Boot,通过整合通用实践,更加自动、智能的依赖管理等,Spring Boot 提供了各种典型应用领域的快速开发基础,所以它是以应用为中心的一个框架集合。

Spring Cloud,可以看作是在 Spring Boot 基础上发展出的更加高层次的框架,它提供了构建分布式系统的通用模式,包含服务发现和服务注册、分布式配置管理、负载均衡、分布式诊断等各种子系统,可以简化微服务系统的构建。

当然,还有针对特定领域的 Spring Security、Spring Data 等。

Spring容器初始化开始:

1.[BeanFactoryPostProcessor]接口实现类的构造器2.[BeanFactoryPostProcessor]的postProcessorBeanFactory方法

3.[BeanPostProcessor]接口实现类的构造器

4.[InstantiationAwareBeanPostProcessorAdapter]构造器

5.[InstantiationAwareBeanPostProcessorAdapter]的postProcessBeforeInstantiation方法(从这里开始初始化bean)

6.[Bean]的构造器

7.[InstantiationAwareBeanPostProcessorAdapter]的postProcessAfterInstantiation

8.[InstantiationAwareBeanPostProcessorAdapter]的postProcessPropertyValues方法

9.[Bean]属性注入,setter方

方法

10.[Bean]如果实现了各种XXXaware接口,依次调用各个setXXX(如BeanNameAware.setBeanName(),BeanFactoryAware.setBeanFactory())

11.[BeanPostProcessor]的postProcessBeforeInitialization方法

12.[InstantiationAwareBeanPostProcessorAdapter]的postProcessBeforeInitialization方法

13.[Bean]自定义的init-method

14.[Bean]如果实现了InitializingBean接口,此时会调用它的afterPropertiesSet方法

15.[BeanPostProcessor]的postProcessAfterInitialization方法(此时bean初始化完成)

16.[InstantiationAwareBeanPostProcessorAdapter]的postProcessInitialization方法(到这里容器初始化完成)

17.业务逻辑bean的使用

Bean的销毁过程:

1.[DisposableBean]的destory方法

2.[Bean]自定义的destory-method方法

说明:如果有多个bean需要初始化,会循环执行5–15。

感觉本篇文章跑题了呢,关于生命周期,只讨论了初始化过程和销毁过程,那么什么时候引发的初始化呢?什么时候触发销毁操作呢?spring容器管理的bean是在容器运行过程中不会被销毁吧?

我来讲讲吧:

首先理解scope:

  1. Singleton(单例) 在整个应用中,只创建bean的一个实例
  2. Propotype(原型) 每次注入或者通过Spring应用上下文获取的时候,都会创建一个新
    的bean实例。
  3. Session(会话) 在Web应用中,为每个会话创建一个bean实例。
  4. Request(请求) 在Web应用中,为每个请求创建一个bean实例。

他们是什么时候创建的:

1一个单例的bean,而且lazy-init属性为false(默认),在Application Context创建的时候构造

2一个单例的bean,lazy-init属性设置为true,那么,它在第一次需要的时候被构造.

3 其他scope的bean,都是在第一次需要使用的时候创建

他们是什么时候销毁的:

1 单例的bean始终 存在与application context中, 只有当 application 终结的时候,才会销毁

2 和其他scope相比,Spring并没有管理prototype实例完整的生命周期,在实例化,配置,组装对象交给应用后,spring不再管理.只要bean本身不持有对另一个资源(如数据库连接或会话对象)的引用,只要删除了对该对象的所有引用或对象超出范围,就会立即收集垃圾.

3 Request: 每次客户端请求都会创建一个新的bean实例,一旦这个请求结束,实例就会离开scope,被垃圾回收.

4 Session: 如果用户结束了他的会话,那么这个bean实例会被GC.

一课一练

请介绍一下 Spring 声明式事务的实现机制,可以考虑将具体过程画图。

第38讲 | 对比Java标准NIO类库,你知道Netty是如何实现更高性能的吗?

第38讲 | 对比Java标准NIO类库,你知道Netty是如何实现更高性能的吗?

模块5 Java应用开发扩展 (4讲)

你知道 Netty 是如何实现更高性能的吗

单独从性能角度,Netty 在基础的 NIO 等类库之上进行了很多改进,例如:

更加优雅的 Reactor 模式实现、灵活的线程模型、利用 EventLoop 等创新性的机制,可以非常高效地管理成百上千的 Channel。

充分利用了 Java 的 Zero-Copy 机制,并且从多种角度,“斤斤计较”般的降低内存分配和回收的开销。例如,使用池化的 Direct Buffer 等技术,在提高 IO 性能的同时,减少了对象的创建和销毁;利用反射等技术直接操纵 SelectionKey,使用数组而不是 Java 容器等。

使用更多本地代码。例如,直接利用 JNI 调用 Open SSL 等方式,获得比 Java 内建 SSL 引擎更好的性能。

在通信协议、序列化等其他角度的优化。

推荐阅读 Norman Maurer 等编写的《Netty 实战》(Netty In Action),如果你想系统学习 Netty,它会是个很好的入门参考。

考点:

Reactor 模式和 Netty 线程模型。

Pipelining、EventLoop 等部分的设计实现细节。

Netty 的内存管理机制、 引用计数 等特别手段。

有的时候面试官也喜欢对比 Java 标准 NIO API,例如,你是否知道 Java NIO 早期版本中的 Epoll 空转问题 ,以及 Netty 的解决方式等。

一课一练

Netty 的线程模型是什么样的?

第39讲 | 谈谈常用的分布式ID的设计方案?Snowflake是否受冬令时切换影响?

第39讲 | 谈谈常用的分布式ID的设计方案?Snowflake是否受冬令时切换影响?

模块5 Java应用开发扩展 (4讲)

常用的分布式 ID 的设计方案?

Snowflake 是否受冬令时切换影响?

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章