Java I/O 模型详解
前言
Java 中有 3 种主要的 I/O 模型:同步阻塞 I/O(BIO)、同步非阻塞 I/O(NIO)和异步非阻塞 I/O(AIO),除了这 3 种主要的 I/O 模型,还有多路复用 I/O 模型和信号驱动模型。它们的区别主要在于处理 I/O 操作时线程的行为方式,以及应用程序对于 I/O 完成时的处理方式。
I/O 模型介绍
I/O 模型的简介
同步阻塞 I/O 模型(Blocking I/O,简称阻塞 I/O)是 Java 最早引入的模型之一,它的特点是在执行 I/O 操作时会阻塞当前线程,直到 I/O 操作完成才会继续执行后续代码。在同步阻塞 I/O 模型中,当一个线程调用读取操作时,如果没有数据可读,线程将一直阻塞在读取操作上,直到有数据到达为止。同样,当一个线程调用写入操作时,如果写缓冲区已满,线程将一直阻塞在写入操作上,直到有空间可用为止。同步阻塞 I/O 模型的优点是简单易用,但其缺点是效率较低,不适用高并发场景,因为线程在等待 I/O 操作完成时会被阻塞,无法处理其他任务。
同步非阻塞 I/O 模型(Non-blocking I/O,简称非阻塞 I/O)是对同步阻塞 I/O 模型(BIO)的改进,从 Java 1.4 开始支持。在同步非阻塞 I/O 模型中,当一个线程调用读取操作时,如果没有数据可读,线程不会被阻塞,而是立即返回一个错误码或空值。同样,当一个线程调用写入操作时,如果写缓冲区已满,线程也不会被阻塞,而是立即返回一个错误码。通过不断地轮询 I/O 操作的状态,同步非阻塞 I/O 模型可以实现在等待 I/O 操作完成的同时处理其他任务。同步非阻塞 I/O 模型的优点是能够提高系统的并发性能,但其缺点是需要频繁地轮询 I/O 操作的状态,会造成 CPU 资源的浪费,而且实现相对复杂,需要一定的编程技巧。这种模型适用于需要处理多个连接但每个连接比较短(轻操作)的场景,如实时通讯系统、聊天服务器等。
多路复用 I/O 模型(Multiplexing I/O)可以实现同时监控多个 I/O 操作的状态。Java 中的多路复用 I/O 一般是建立在同步非阻塞 I/O 模型(NIO)基础之上实现的,比如 Netty 网络编程框架。在多路复用 I/O 模型中,一个线程可以同时监听多个 I/O 操作的状态,当某个 I/O 操作就绪时,线程可以进行相应的读取或写入操作。通过这种方式,多路复用 I/O 模型可以在一个线程中处理多个 I/O 操作,提高系统的并发性能。多路复用 I/O 模型的优点是能够有效地减少线程的数量,降低系统资源的消耗,但其缺点是实现复杂度较高,需要一定的编程技巧。
异步非阻塞 I/O 模型(Asynchronous I/O,简称异步 I/O)是最高级别的 I/O 模型之一,性能和吞吐量最高,从 Java 1.7 开始支持。它通过将 I/O 操作的结果通知给应用程序,来实现非阻塞的 I/O 操作。在异步非阻塞 I/O 模型中,应用程序发起一个 I/O 操作后,不需要等待操作完成,而是可以继续执行其他任务。当 I/O 操作完成后,操作系统会通知应用程序,应用程序再进行相应的处理。异步非阻塞 I/O 模型的优点是能够充分利用系统资源,提高系统的并发性能,但其缺点是需要操作系统的支持,在某些操作系统(如 Windows)上的支持不如 NIO 成熟,对于编程人员来说,实现相对复杂。这种模型适用于需要处理多个连接且每个连接比较长(重操作),并且要求高性能、高并发的场景,例如高性能服务器、流媒体服务器等。
JMeter 压测教程之二 JVM 调优
SpringBoot 3 开发随笔
SpringBoot 3 版本
2022 年 11 月 24 日,SpringBoot 3.0 正式发布了。此版本包含了 12 个月以来 151 个人的 5700 多次 Commit 的工作结晶。这是自 4.5 年前发布 2.0 以来,Spring Boot 的第一次重大修订。它也是第一个支持 Spring Framework 6.0 和 GraalVM 的 Spring Boot GA 版本。
新变化
- 支持响应式编程
- 支持 Spring Framework 6.0
- 支持 GraalVM native images
- Spring 自身与第三方包版本升级
- 最低支持 JDK 17,最高支持 JDK 19
- 从 Java EE API (Javax) 迁移到 Jakarta EE API
- 自动配置的包位置变化
- 旧版本:
META-INF/spring.factories
- 新版本:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- 旧版本:
JMeter 压测教程之一基础使用
Java 的五种代理实现方式
大纲
前言
本文主要介绍 Java 的五种代理实现方式,包括 JDK 动态代理、Cglib、ASM、Javassist、Byte Buddy,点击 下载完整的案例代码。
准备工作
先定义出一个接口和相应的实现类,方便后续使用代理类在方法中添加日志信息。
- 接口
1 | public interface IUserApi { |
Java 的静态代理使用
如何估算 Java 线程池的大小与队列长度
估算算法
第一种估算算法
先来一个天真的估算算法:假设要求一个系统的 TPS(Transaction Per Second 或者 Task Per Second)至少为 20,然后假设每个 Transaction 由一个线程完成,继续假设平均每个线程处理一个 Transaction 的时间为 4s。那么问题可以转化为:如何设计线程池大小,使得可以在 1s 内处理完 20 个 Transaction?这里计算过程可以很简单,每个线程的处理能力为 0.25TPS,那么要达到 20TPS,显然需要 20/0.25=80 个线程。
很显然这个估算算法很天真,因为它没有考虑到 CPU 数目。一般服务器的 CPU 核数为 16 或者 32,如果有 80 个线程,那么肯定会带来太多不必要的线程上下文切换开销。
第二种估算算法
第二种估算算法比较简单,但不知是否可行(N 为 CPU 总核数):
- 如果是 CPU 密集型应用,则线程池大小设置为 N+1
- 如果是 IO 密集型应用,则线程池大小设置为 2N+1
如果一台服务器上只部署这一个应用并且只有一个线程池,那么这种估算或许合理,具体还需自行测试验证。
Java 代码规范检测与格式化(超详细)
前言
本文主要介绍如何检测 Java 代码规范与格式化 Java 代码,包括 IDEA 插件与 Maven 插件的使用。
代码规范检测插件
IDEA 代码规范检测插件
IDEA 可以使用 CheckStyle-IDEA 插件来检测 Java 代码的规范,它可以保证每位提交者的代码规范都保持一致。值得一提的是,CheckStyle-IDEA
插件只能检测代码的规范,并不能格式化代码。
创建规则文件
在项目中创建 checkstyle.xml
规则文件,例如路径为 config/checkstyle/checkstyle.xml
。
提示
- Alibaba Nacos 的 CheckStyle 规则文件如下,要求 CheckStyle 的版本至少为
8.30
VuePress 渲染 Mermaid 绘图
前言
本文将介绍 VuePress 如何渲染 Mermaid 绘图,适用于 VuePress 1.x 与 VuePress 2.x。
VuePress 1.x
VuePress 1.x 可以直接安装第三方插件 vuepress-plugin-mermaidjs 来渲染 Mermaid 绘图,插件的详细文档可看 这里。
安装插件
安装插件时必须指定具体的版本号,否则默认会安装最新版本的插件,最新版本不兼容 VuePres 1.x。
1 | $ npm install vuepress-plugin-mermaidjs@1.9.1 -D |
配置插件
编辑 VuePress 1.x 的 .vuepress/config.js
配置文件,新增 mermaidjs
插件,如下所示:
1 | module.exports = { |