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

《Java 简易速速上手小册》第8章:Java 性能优化(2024 最新版)

在这里插入图片描述

文章目录

  • 8.1 性能评估工具 - 你的性能探测仪
    • 8.1.1 基础知识
    • 8.1.2 重点案例:使用 VisualVM 监控应用性能
    • 8.1.3 拓展案例 1:使用 JProfiler 分析内存泄漏
    • 8.1.4 拓展案例 2:使用 Gatling 进行 Web 应用压力测试
  • 8.2 JVM 调优 - 魔法引擎的调校
    • 8.2.1 基础知识
    • 8.2.2 重点案例:优化 Web 应用的 JVM 设置
    • 8.2.3 拓展案例 1:使用 Parallel GC 优化批处理应用
    • 8.2.4 拓展案例 2:减少 Full GC 的发生频率
  • 8.3 代码优化策略 - 编码的艺术
    • 8.3.1 基础知识
    • 8.3.2 重点案例:优化搜索算法
    • 8.3.3 拓展案例 1:循环优化
    • 8.3.4 拓展案例 2:利用并发提升数据处理效率

8.1 性能评估工具 - 你的性能探测仪

在Java应用的性能优化之旅中,首先需要做的就是准确地评估和定位现有性能问题。幸运的是,我们有一系列强大的工具可以帮助我们完成这个任务。

8.1.1 基础知识

  • VisualVM: 免费工具,提供了一套可视化界面来监控Java应用的CPU、内存使用情况,线程和堆信息等。它还可以对Java应用进行性能分析和内存分析。

  • JProfiler: 商业工具,提供了更深入的性能分析功能,包括实时的CPU、内存使用监控,内存泄漏侦测,数据库访问分析等。

  • Gatling: 专注于Web应用的性能测试工具,可以模拟高并发访问,并生成详细的性能报告。

8.1.2 重点案例:使用 VisualVM 监控应用性能

我们将展示如何使用VisualVM对Java应用进行基本的性能监控。

步骤:

  1. 下载并安装VisualVM。
  2. 启动你的Java应用。
  3. 打开VisualVM,从左侧进程列表中选择你的Java应用。
  4. 查看“监视器”和“分析器”标签页,以获取CPU和内存的使用情况,以及线程的信息。

示例代码(一个简单的Java程序,用于生成CPU和内存负载):

public class PerformanceLoadGenerator {public static void main(String[] args) {for (int i = 0; i < 100; i++) {new Thread(() -> {while (true) {Math.pow(Math.random(), Math.random());}}).start();}}
}

8.1.3 拓展案例 1:使用 JProfiler 分析内存泄漏

在这个案例中,我们会演示如何使用JProfiler来诊断和分析Java应用中的内存泄漏。

步骤:

  1. 启动JProfiler并连接到你的Java应用。
  2. 在“堆栈”标签页中,开始记录内存分配。
  3. 执行一系列操作来模拟用户行为。
  4. 停止记录,并查看“类视图”或“对象视图”找到可能的内存泄漏。

示例代码(一个可能存在内存泄漏的Java程序):

import java.util.ArrayList;
import java.util.List;public class MemoryLeakExample {private static final List<Double> list = new ArrayList<>();public static void main(String[] args) {while (true) {list.add(Math.random());}}
}

8.1.4 拓展案例 2:使用 Gatling 进行 Web 应用压力测试

最后,我们将演示如何使用Gatling工具对Web应用进行压力测试,以评估其在高并发情况下的性能。

步骤:

  1. 安装Gatling并创建一个测试脚本。
  2. 定义模拟的用户行为和请求参数。
  3. 运行Gatling测试。
  4. 分析测试报告,找出性能瓶颈。

示例Gatling脚本(模拟多用户访问Web应用):

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._class BasicSimulation extends Simulation {val httpProtocol = http.baseUrl("http://yourwebapp.com").acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8").doNotTrackHeader("1")val scn = scenario("BasicSimulation").exec(http("request_1").get("/")).pause(5)setUp(scn.inject(atOnceUsers(100))).protocols(httpProtocol)
}

通过以上案例,你已经学会了如何使用VisualVM进行基本的性能监控,使用JProfiler分析内存泄漏,以及使用Gatling进行Web应用的压力测试。掌握这些工具将使你能够更加自信地面对性能优化的挑战。

在这里插入图片描述


8.2 JVM 调优 - 魔法引擎的调校

Java虚拟机(JVM)是Java应用运行的心脏,正确调优JVM可以显著提升应用性能,就像为你的魔法引擎进行精细调校一样,让它运行得更快、更高效。

8.2.1 基础知识

  • 堆内存设置:JVM堆内存是Java对象生存的地方。通过调整堆内存的大小(使用-Xms设置初始堆大小,-Xmx设置最大堆大小),可以优化垃圾收集性能,避免内存溢出。

  • 垃圾回收器选择:不同的垃圾回收器(GC)适用于不同的场景和应用需求。常见的垃圾回收器有Serial GC、Parallel GC、CMS、G1等。

  • JVM监控和诊断工具:使用JVM监控工具(如jstat、jmap、jstack)和诊断工具(如Java Mission Control)可以帮助识别性能瓶颈和内存泄漏。

8.2.2 重点案例:优化 Web 应用的 JVM 设置

假设你负责一个高流量的Java Web应用,此应用在高负载时出现了性能瓶颈。通过调优JVM设置,我们可以提高应用性能。

步骤:

  1. 识别性能瓶颈:使用JVM监控工具观察应用在高负载时的性能指标。
  2. 调整堆内存大小:根据应用的实际使用情况调整-Xms-Xmx参数,比如设置-Xms4g -Xmx4g,为JVM堆分配更多内存。
  3. 选择合适的垃圾回收器:对于需要低延迟的Web应用,可以考虑使用G1垃圾回收器,设置-XX:+UseG1GC

示例JVM启动参数

java -Xms4g -Xmx4g -XX:+UseG1GC -jar your-web-app.jar

8.2.3 拓展案例 1:使用 Parallel GC 优化批处理应用

对于一些后台运行的大数据处理或批处理应用,吞吐量是最重要的指标。Parallel GC是一个以达到高吞吐量为目标的垃圾回收器。

示例JVM启动参数

java -Xms8g -Xmx8g -XX:+UseParallelGC -jar your-batch-app.jar

通过设置-XX:+UseParallelGC,我们告诉JVM使用Parallel GC,这对于提高批处理任务的处理速度非常有效。

8.2.4 拓展案例 2:减少 Full GC 的发生频率

频繁的Full GC会严重影响应用的性能。通过调整新生代和老年代的大小,可以减少Full GC的发生频率。

示例JVM启动参数

java -Xms4g -Xmx4g -XX:NewRatio=3 -jar your-app.jar

这里-XX:NewRatio=3表示老年代与新生代的比例是3:1,给老年代分配更多的内存空间可以减少对象晋升到老年代的频率,从而减少Full GC的发生。

通过以上案例,你已经学会了如何针对不同类型的Java应用进行JVM调优,从而提升应用的性能。记住,JVM调优是一个反复试验和评估的过程,每个应用的最佳配置都是独一无二的。使用正确的工具和策略,你的Java应用将运行得更加流畅和高效。

在这里插入图片描述


8.3 代码优化策略 - 编码的艺术

代码优化是提升Java应用性能的基石。通过精简和优化代码,我们可以减少资源消耗,提高执行效率。下面是一些基本的代码优化策略,以及如何应用这些策略来提升你的Java应用性能。

8.3.1 基础知识

  • 算法优化:选择合适的算法对性能影响巨大。时间复杂度和空间复杂度是衡量算法性能的关键指标。
  • 循环优化:减少循环次数和循环内的计算量,避免在循环内进行不必要的操作。
  • 数据结构选择:根据数据的使用模式选择合适的数据结构,比如在频繁查找操作中使用HashMap而不是ArrayList
  • 避免重复计算:缓存计算结果以避免重复计算,特别是在计算成本高昂的情况下。
  • 利用并发编程:合理利用多线程或并发工具来分摊任务,提升执行效率。

8.3.2 重点案例:优化搜索算法

假设我们有一个任务,需要在一个大型数据集中频繁搜索特定元素。原始实现使用了ArrayList,我们将通过优化算法和数据结构来提升搜索性能。

原始实现:

import java.util.ArrayList;
import java.util.List;public class SearchExample {public static boolean search(List<Integer> data, int key) {for (int item : data) {if (item == key) {return true;}}return false;}public static void main(String[] args) {List<Integer> data = new ArrayList<>();// 假设data被初始化并填充了大量元素boolean found = search(data, 12345);System.out.println("Found: " + found);}
}

优化后的实现:

ArrayList替换为HashSet,提升搜索性能。

import java.util.HashSet;
import java.util.Set;public class OptimizedSearchExample {public static boolean search(Set<Integer> data, int key) {return data.contains(key);}public static void main(String[] args) {Set<Integer> data = new HashSet<>();// 假设data被初始化并填充了大量元素boolean found = search(data, 12345);System.out.println("Found: " + found);}
}

8.3.3 拓展案例 1:循环优化

对于一个处理大量数据的循环,优化其执行路径可以显著提升性能。

优化前:

for (int i = 0; i < data.size(); i++) {if (expensiveComputation(data.get(i))) {// 处理结果}
}

优化后:

将条件判断移出循环,减少循环内的计算量。

for (int i = 0; i < data.size(); i++) {preComputedResult = preCompute(data.get(i));if (preComputedResult) {// 处理结果}
}

8.3.4 拓展案例 2:利用并发提升数据处理效率

对于数据处理密集型任务,通过并行处理可以显著缩短总体执行时间。

示例代码:

使用Java 8的Stream API进行并行处理。

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;public class ParallelProcessingExample {public static void main(String[] args) {List<Integer> data = IntStream.rangeClosed(1, 1000000).boxed().collect(Collectors.toList());long startTime = System.currentTimeMillis();data.parallelStream().forEach(ParallelProcessingExample::expensiveOperation);long endTime = System.currentTimeMillis();System.out.println("Processing time: " + (endTime - startTime) + "ms");}public static void expensiveOperation(int item) {// 模拟一个耗时操作try {Thread.sleep(1);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}

通过这些案例,我们看到了通过算法优化、循环优化和利用并发编程等策略,可以显著提升Java应用的性能。性能优化是一个持续的过程,始终需要我们在实践中不断地探索和学习。

相关文章:

《Java 简易速速上手小册》第8章:Java 性能优化(2024 最新版)

文章目录 8.1 性能评估工具 - 你的性能探测仪8.1.1 基础知识8.1.2 重点案例&#xff1a;使用 VisualVM 监控应用性能8.1.3 拓展案例 1&#xff1a;使用 JProfiler 分析内存泄漏8.1.4 拓展案例 2&#xff1a;使用 Gatling 进行 Web 应用压力测试 8.2 JVM 调优 - 魔法引擎的调校8…...

mysql全国省市县三级联动创表sql(一)

1. 建表sql CREATE TABLE province (id VARCHAR ( 32 ) PRIMARY KEY COMMENT 主键,code CHAR ( 6 ) NOT NULL COMMENT 省份编码,name VARCHAR ( 40 ) NOT NULL COMMENT 省份名称 ) COMMENT 省份信息表;CREATE TABLE city (id VARCHAR ( 32 ) PRIMARY KEY COMMENT 主键,code …...

go面试题--使用两个goroutine交替打印数字与字母

使用两个goroutine交替打印数字与字母 题目如下&#xff1a; 使用两个goroutine交替打印序列&#xff0c;一个goroutine打印数字&#xff0c;另外一个goroutine打印字母&#xff0c;最终效果如下&#xff1a; 12AB34CD56EF78GH910IZ1112KL1314MN1516OP1718QR1920ST2122UV2324W…...

DolphinScheduler-3.2.0 集群搭建

目录 一、基础环境准备 1.1 组件下载地址 1.2 前置准备工作 二、 DolphinScheduler集群部署 2.1 解压安装包 2.2 配置数据库 2.3 准备 DolphinScheduler 启动环境 2.3.1 配置用户免密及权限 2.3.2 配置机器 SSH 免密登陆 2.3.3 启动 zookeeper集群 2.3.4 修改instal…...

07:Kubectl 命令详解|K8S资源对象管理|K8S集群管理(重难点)

Kubectl 命令详解&#xff5c;K8S资源对象管理&#xff5c;K8S集群管理 kubectl管理命令kubectl get 查询资源常用的排错命令kubectl run 创建容器 POD原理pod的生命周期 k8s资源对象管理资源文件使用资源文件管理对象Pod资源文件deploy资源文件 集群调度的规则扩容与缩减集群更…...

【设计模式】springboot3项目整合模板方法深入理解设计模式之模板方法(Template Method)

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;底层原理高级进阶》 &#x1f680…...

Windows搭建docker+k8s

安装Docker Desktop 从官网下载&#xff0c;然后直接安装即可&#xff0c;过程很简单&#xff0c;一直Next就行。 有一点需要注意就是要看好对应的版本&#xff0c;因为后边涉及到版本的问题。 https://www.docker.com/products/docker-desktop 安装完成&#xff0c;双击图…...

年假作业10

一、选择题 BBDBACCCAD 二、填空题 1,4,13,40 3715 358 5 2 6 1 5 4 8 2 0 2 三、编程题 1、 #include <iostream> #include<array> #include <limits> using namespace std; int main() {array<int,10> score;array<int,10>::iterat…...

[ai笔记4] 将AI工具场景化,应用于生活和工作

欢迎来到文思源想的AI空间&#xff0c;这是技术老兵重学ai以及成长思考的第4篇分享内容&#xff01; 转眼已经到了大年初三&#xff0c;但是拜年的任务还只完成了一半&#xff0c;准备的大部头的书&#xff0c;现在也就看了两本&#xff0c;还好AI笔记通过每天早起坚持了下来。…...

【生产实测可用】Redis修改集群弱口令

起因 漏扫redis连接发现弱口令需要修改 先连上去看看是空口令还是弱口令 redis-cli -p 6379 -h a.b.c.d info sentinel找到启动服务器的配置文件 cp -av /app/redis-7001/redis.conf /app/redis-7001/redis.conf.bak20240207 echo "requirepass 口令" >>/a…...

备战蓝桥杯---图论基础理论

图的存储&#xff1a; 1.邻接矩阵&#xff1a; 我们用map[i][j]表示i--->j的边权 2.用vector数组&#xff08;在搜索专题的游戏一题中应用过&#xff09; 3.用邻接表&#xff1a; 下面是用链表实现的基本功能的代码&#xff1a; #include<bits/stdc.h> using nam…...

[office] excel2003进行可视性加密的方法 #媒体#其他#知识分享

excel2003进行可视性加密的方法 Excel如何对重要文件进行可视性的加密处理呢?下面是小编带来的关于excel2003进行可视性加密的方法&#xff0c;希望阅读过后对你有所启发! excel2003进行可视性加密的方法&#xff1a; 可视性加密步骤1&#xff1a;打开你要加密的excel2003文档…...

算法沉淀——分治算法(leetcode真题剖析)

算法沉淀——分治算法 快排思想01.颜色分类02.排序数组03.数组中的第K个最大元素04.库存管理 III 归并思想01.排序数组02.交易逆序对的总数03.计算右侧小于当前元素的个数04.翻转对 分治算法是一种解决问题的算法范式&#xff0c;其核心思想是将一个大问题分解成若干个小问题&a…...

Qt 进程守护程序

Qt 进程守护程序 简单粗暴的监控&#xff0c;方法可整合到其他代码。 一、windows环境下 1、进程查询函数 processCount函数用于查询系统所有运行的进程中该进程运行的数量&#xff0c;比如启动了5个A进程&#xff0c;该函数查询返回的结果就为5。 windows下使用了API接口查询…...

Linux_文件系统

假定外部存储设备为磁盘&#xff0c;文件如果没有被使用&#xff0c;那么它静静躺在磁盘上&#xff0c;如果它被使用&#xff0c;则文件将被加载进内存中。故此&#xff0c;可以将文件分为内存文件和磁盘文件。 内存文件 磁盘文件 软、硬链接 一.内存文件 1.1 c语言的文件接口 …...

算法沉淀——链表(leetcode真题剖析)

算法沉淀——链表 01.两数相加02.两两交换链表中的节点03.重排链表04.合并 K 个升序链表05.K个一组翻转链表 链表常用技巧 1、画图->直观形象、便于理解 2、引入虚拟"头节点" 3、要学会定义辅助节点&#xff08;比如双向链表的节点插入&#xff09; 4、快慢双指针…...

Flink从入门到实践(一):Flink入门、Flink部署

文章目录 系列文章索引一、快速上手1、导包2、求词频demo&#xff08;1&#xff09;要读取的数据&#xff08;2&#xff09;demo1&#xff1a;批处理&#xff08;离线处理&#xff09;&#xff08;3&#xff09;demo2 - lambda优化&#xff1a;批处理&#xff08;离线处理&…...

python分离字符串 2022年12月青少年电子学会等级考试 中小学生python编程等级考试二级真题答案解析

目录 python分离字符串 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python分离字符串 2022年12月 python编程等级考试级编程题 一、题目要…...

Excel练习:折线图突出最大最小值

Excel练习&#xff1a;折线图突出最大最小值 ​​ 要点&#xff1a;NA值在折现图中不会被绘制&#xff0c;看似一条线&#xff0c;实际是三条线。换成0值和""都不行。 ‍ 查看所有已分享Excel文件-阿里云 ‍ 学习的这个视频&#xff1a;Excel折线图&#xff0c…...

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之MenuItem组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之MenuItem组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、MenuItem组件 用来展示菜单Menu中具体的item菜单项。 子组件 无。 接口 Men…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...