Java性能优化的七个方向

article/2025/11/9 8:20:17

博客主页:https://tomcat.blog.csdn.net
博主昵称:农民工老王
主要领域:Java、Linux、K8S
期待大家的关注💖点赞👍收藏⭐留言💬
家乡

目录

  • 概述
  • 复用优化
  • 计算优化
    • 并行执行
    • 变同步为异步
    • 惰性加载
  • 结果集优化
  • 资源冲突优化
  • 算法优化
  • 高效实现
  • JVM 优化
  • 小结

在上一篇文章,我介绍了性能分析的各种指标,这样在做性能优化的时候,就有了具体的优化目标和衡量方法,优化效果也不会仅仅停留在直观感觉上。

了解了优化目标后,那接下来应该从哪些方面入手呢?本文主要侧重于理论分析,我们从整体上看一下 Java 性能优化都有哪些可以遵循的规律。本文主讲理论。关于实践,后续的文章会用较多的案例来细化本文的知识点,适合反复思考和归纳。

概述

性能优化根据优化的类别,分为业务优化和技术优化。业务优化产生的效果也是非常大的,但它属于产品和管理的范畴。同作为程序员,在平常工作中,我们面对的优化方式,主要是通过一系列的技术手段,来完成对既定的优化目标。这一系列的技术手段,我大体归纳为如图以下 7 类:
在这里插入图片描述可以看到,优化方式集中在对计算资源和存储资源的规划上。优化方法中有多种用空间换时间的方式,但只照顾计算速度,而不考虑复杂性和空间问题,也是不可取的。我们要做的,就是在照顾性能的前提下,达到资源利用的最优状态。

接下来,我简要介绍一下这7个优化方向。如果你感觉比较枯燥,那也没关系,我们本文的目的,就是让你的脑海里有一个总分的概念,以及对理论基础有一个整体的认识。

复用优化

在写代码的时候,你会发现有很多重复的代码可以提取出来,做成公共的方法。这样,在下次用的时候,就不用再费劲写一遍了。

这种思想就是复用。上面的描述是编码逻辑上的优化,对于数据存取来说,有同样的复用情况。无论是在生活中还是编码中,重复的事情一直在发生,如果没有复用,工作和生活就会比较累。

在软件系统中,谈到数据复用,我们首先想到的就是缓冲和缓存。注意这两个词的区别,它们的意义是完全不同的,很多同学很容易搞混,在这里简单地介绍一下。

  • 缓冲(Buffer),常见于对数据的暂存,然后批量传输或者写入。多使用顺序方式,用来缓解不同设备之间频繁地、缓慢地随机写,缓冲主要针对的是写操作。
  • 缓存(Cache),常见于对已读取数据的复用,通过将它们缓存在相对高速的区域,缓存主要针对的是读操作。

与之类似的,是对于对象的池化操作,比如数据库连接池、线程池等,在 Java 中使用得非常频繁。由于这些对象的创建和销毁成本都比较大,我们在使用之后,也会将这部分对象暂时存储,下次用的时候,就不用再走一遍耗时的初始化操作了。

计算优化

并行执行

现在的 CPU 发展速度很快,绝大多数硬件,都是多核。要想加快某个任务的执行,最快最优的解决方式,就是让它并行执行。并行执行有以下三种模式。

第一种模式是多机,采用负载均衡的方式,将流量或者大的计算拆分成多个部分,同时进行处理。比如,Hadoop 通过 MapReduce 的方式,把任务打散,多机同时进行计算。

第二种模式是采用多进程。比如 Nginx,采用 NIO 编程模型,Master 统一管理 Worker 进程,然后由 Worker 进程进行真正的请求代理,这也能很好地利用硬件的多个 CPU。

第三种模式是使用多线程,这也是 Java 程序员接触最多的。比如 Netty,采用 Reactor 编程模型,同样使用 NIO,但它是基于线程的。Boss 线程用来接收请求,然后调度给相应的 Worker 线程进行真正的业务计算。

像 Golang 这样的语言,有更加轻量级的协程(Coroutine),协程是一种比线程更加轻量级的存在,但目前在 Java 中还不太成熟,就不做过多介绍了,但本质上,它也是对于多核的应用,使得任务并行执行。

变同步为异步

再一种对于计算的优化,就是变同步为异步,这通常涉及编程模型的改变。同步方式,请求会一直阻塞,直到有成功,或者失败结果的返回。虽然它的编程模型简单,但应对突发的、时间段倾斜的流量,问题就特别大,请求很容易失败。

异步操作可以方便地支持横向扩容,也可以缓解瞬时压力,使请求变得平滑。同步请求,就像拳头打在钢板上;异步请求,就像拳头打在海绵上。你可以想象一下这个过程,后者肯定是富有弹性的,体验更加友好。

惰性加载

最后一种,就是使用一些常见的设计模式来优化业务,提高体验,比如单例模式、代理模式等。举个例子,在绘制 Swing 窗口的时候,如果要显示比较多的图片,就可以先加载一个占位符,然后通过后台线程慢慢加载所需要的资源,这就可以避免窗口的僵死。

结果集优化

接下来介绍一下对结果集的优化。举个比较直观的例子,我们都知道 XML 的表现形式是非常好的,那为什么还有 JSON 呢?除了书写要简单一些,一个重要的原因就是它的体积变小了,传输效率和解析效率变高了,像 Google 的 Protobuf,体积就更小了一些。虽然可读性降低,但在一些高并发场景下(如 RPC),能够显著提高效率,这是典型的对结果集的优化。

这是由于我们目前的 Web 服务,都是 C/S 模式。数据从服务器传输到客户端,需要分发多份,这个数据量是急剧膨胀的,每减少一小部分存储,都会有比较大的传输性能和成本提升。

像 Nginx,一般都会开启 GZIP 压缩,使得传输的内容保持紧凑。客户端只需要一小部分计算能力,就可以方便解压。由于这个操作是分散的,所以性能损失是固定的。

了解了这个道理,我们就能看到对于结果集优化的一般思路,你要尽量保持返回数据的精简。一些客户端不需要的字段,那就在代码中,或者直接在 SQL 查询中,就把它去掉。

对于一些对时效性要求不高,但对处理能力有高要求的业务。我们要吸取缓冲区的经验,尽量减少网络连接的交互,采用批量处理的方式,增加处理速度。

结果集合很可能会有二次使用,你可能会把它加入缓存中,但依然在速度上有所欠缺。这个时候,就需要对数据集合进行处理优化,采用索引或者 Bitmap 位图等方式,加快数据访问速度。

资源冲突优化

我们在平常的开发中,会涉及很多共享资源。这些共享资源,有的是单机的,比如一个 HashMap;有的是外部存储,比如一个数据库行;有的是单个资源,比如 Redis 某个 key 的Setnx;有的是多个资源的协调,比如事务、分布式事务等。

现实中的性能问题,和锁相关的问题是非常多的。大多数我们会想到数据库的行锁、表锁、Java 中的各种锁等。在更底层,比如 CPU 命令级别的锁、JVM 指令级别的锁、操作系统内部锁等,可以说无处不在。

只有并发,才能产生资源冲突。也就是在同一时刻,只能有一个处理请求能够获取到共享资源。解决资源冲突的方式,就是加锁。再比如事务,在本质上也是一种锁。

按照锁级别,锁可分为乐观锁和悲观锁,乐观锁在效率上肯定是更高一些;按照锁类型,锁又分为公平锁和非公平锁,在对任务的调度上,有一些细微的差别。

对资源的争用,会造成严重的性能问题,所以会有一些针对无锁队列之类的研究,对性能的提升也是巨大的。

算法优化

算法能够显著提高复杂业务的性能,但在实际的业务中,往往都是变种。由于存储越来越便宜,在一些 CPU 非常紧张的业务中,往往采用空间换取时间的方式,来加快处理速度。

算法属于代码调优,代码调优涉及很多编码技巧,需要使用者对所使用语言的 API 也非常熟悉。有时候,对算法、数据结构的灵活使用,也是代码优化的一个重要内容。比如,常用的降低时间复杂度的方式,就有递归、二分、排序、动态规划等。

一个优秀的实现,比一个拙劣的实现,对系统的影响是非常大的。比如,作为 List 的实现,LinkedList 和 ArrayList 在随机访问的性能上,差了好几个数量级;又比如,CopyOnWriteList 采用写时复制的方式,可以显著降低读多写少场景下的锁冲突。而什么时候使用同步,什么时候是线程安全的,也对我们的编码能力有较高的要求。

这部分的知识,就需要我们在平常的工作中注意积累,后面的课时中,也会挑比较重要的知识点穿插讲解。

高效实现

在平时的编程中,尽量使用一些设计理念良好、性能优越的组件。比如,有了 Netty,就不用再选择比较老的 Mina 组件。而在设计系统时,从性能因素考虑,就不要选 SOAP 这样比较耗时的协议。再比如,一个好的语法分析器(比如使用 JavaCC),其效率会比正则表达式高很多。

总之,如果通过测试分析,找到了系统的瓶颈点,就要把关键的组件,使用更加高效的组件进行替换。在这种情况下,适配器模式是非常重要的。这也是为什么很多公司喜欢在现有的组件之上,再抽象一层自己的;而当在底层组件进行切换的时候,上层的应用并无感知。

JVM 优化

因为 Java 是运行在 JVM 虚拟机之上,它的诸多特性,就要受到 JVM 的制约。对 JVM 虚拟机进行优化,也能在一定程度上能够提升 JAVA 程序的性能。如果参数配置不当,甚至会造成 OOM 等比较严重的后果。

目前被广泛使用的垃圾回收器是 G1,通过很少的参数配置,内存即可高效回收。CMS 垃圾回收器已经在 Java 14 中被移除,由于它的 GC 时间不可控,有条件应该尽量避免使用。

JVM 性能调优涉及方方面面的取舍,往往是牵一发而动全身,需要全盘考虑各方面的影响。所以了解 JVM 内部的一些运行原理,还是特别重要的,它有益于我们加深对代码更深层次的理解,帮助我们书写出更高效的代码。

小结

以上就是代码优化的 7 个大方向,我们通过简要的介绍,让大家对性能优化的内容有了大体的了解。这7大方向是代码优化的最主要方向,当然,性能优化还包含数据库优化、操作系统优化、架构优化等其他一些内容,这些不是我们的重点,在后面的文章中,我们也只做简要的介绍。

接下来,我们会了解一些性能评估工具,了解操作系统的一些资源限制,然后针对这7个优化点,进行展开讨论。本文时适合案例分析后回读,更加能够加深你对 Java 性能优化的理解。


如需转载,请注明本文的出处:农民工老王的CSDN博客https://blog.csdn.net/monarch91 。


http://chatgpt.dhexx.cn/article/jK7dGZMe.shtml

相关文章

JAVA性能优化实例

目录 概述 Sql性能优化 多线程 利用内存缓存 功能优化 参考博客 概述 性能优化的几个点,大致可以分为: sql优化使用多线程利用内存,缓存等,将固定不常更改的数据放入在,存取更快的内存当中功能实现逻辑优化 Sql性…

10种简单的Java性能优化学习

10种简单的Java性能优化学习 你是否正打算优化hashCode()方法?是否想要绕开正则表达式?Lukas Eder介绍了很多简单方便的性能优化小贴士以及扩展程序性能的技巧。 最近“全网域(Web Scale)”一词被炒得火热,人们也正在…

Java性能优化实践:分享Java性能优化的实践经验

Java性能优化是一个非常重要的话题,在现代软件开发中扮演着至关重要的角色。在本篇博客中,我将分享一些Java性能优化的实践经验,包括使用JavaProfiler分析程序性能、使用JMH进行基准测试、优化JVM参数等,帮助开发者更好地理解Java…

11 个简单的 Java 性能调优技巧

大多数开发人员理所当然地以为性能优化很复杂,需要大量的经验和知识。好吧,不能说这是完全错误的。优化应用程序以获得最佳性能不是一件容易的事情。但是,这并不意味着如果你不具备这些知识,就不能做任何事情。这里有11个易于遵循…

Java性能优化

文章目录 一、JVM内存模型1.1、程序计数器(Program Counter Register)1.2、JVM虚拟机栈(JVM Stacks)1.3、本地方法栈(Native Method Stacks)1.4、堆(Heap)1.5、方法区(Me…

Java性能优化的50个细节(珍藏版)

在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身。养成良好的编码习惯非常重要,能够显著地提升程序性能。 1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要…

GNU-ARM程序开发(一)----GNU开发环境和工具

什么是GNU GNU计划,又称革奴计划。是由Richard Stallman在1983年9月27日公开发起的。目标是创建一套完全免费、自由的操作系统,基本原则是源代码共享及思想共享。 所有在GNU计划下开发的软件均为GNU软件。 为保证GNU软件可以自由地“使用、复制、修改和发…

【ARM编程】ARM介绍

01.ARM目录 ARM目录 01.ARM目录02.前言03.计算机体系结构分类04.ARM公司05.ARM应用领域06.ARM基本架构07.ARM各体系架构版本7.1 ARM版本Ⅰ:V1版架构7.2 ARM版本 Ⅱ:V2版架构7.3 ARM版本 Ⅲ:V3版架构7.4 ARM版本 Ⅳ: V4版架构7.5 A…

ARM开发环境

目录 前言一、Ubuntu及linux系统基础知识1.shell命令的运用2.Tool的安装:3.deb是软件包,dpkg是手动安装工具,apt是自动安装工具,4.Linux文件系统5.gcc编译器 二、开发环境搭建1.vim编辑器2.与windows文件互传3.VSCode使用4.NFS网络…

ARM开发环境下载地址大全

MDK5.3.8a(Keil5)最新下载地址 超链接如下,点击直达: Keil MDK (Keil Licensing) (MDK000) (arm.com) 实际网址如下所示: https://developer.arm.com/downloads/view/MDK000 Arm Compiler for Embedded下载地址 超链接如下,点击直…

什么是ARM?

原文 一、ARM是什么? ARM既可以认为是一个公司的名字 ,也可以认为是对一类处理器的统称 ,还可以认为是一种技术的名字 。 ARM公司是专门从事基于RISC技术芯片设计开发 的公司,作为知识产权供应商,本身不直接从事芯片…

X86ARM架构

这里写目录标题 cpu架构arm架构ARM架构图 x86架构arm架构和x86架构的区别CISC Vs RISCWindows如何查看系统是ARM64还是X64架构 32位与64位的区别巨头公司国产cpu公司 cpu架构 CPU 的全称是"中央处理单元",它是计算机的核心,计算都由它来完成。…

ARM开发——常见仿真器

搞嵌入式开发和ARM开发搞了半辈子了,调试程序是不可避免的。接触了那么多的调试规范、调试工具、调试手段,彼此之间的关系却也不是特别清楚,今天就来捋一捋: JTAG协议 JTAG(Joint Test Action Group,联合…

ARM开发---基础认识

本文适合初次接触ARM的的初学者,主要以基础知识点和科普为主. 文章目录 前言一、ARM是什么?二、ARM的特点三、ARM的使用场景1.计算机组成2.架构3.指令集4.指令解析5.工作模式 四、寄存器总结 前言 提起ARM,没有接触过的朋友可能第一反应是英…

【嵌入式】Linux开发工具arm-linux-gcc安装及使用

arm-linux-gcc 知识架构及层次 — 程序编译及调试嵌入式交叉编译器安装配置主机目标板开发模式ARM微处理器/Linux系统下编译器编译器下载及安装 arm-linux-gcc工具使用-E-S-c -o-include file-I dir-I-iprefix prefix 和 -iwithprefix dir-l库名 -L目录gcc 优化 课后作业 Linux…

ARM 编译器 Arm Compiler for Embedded 6 相关工具链简介

目录 1, Introduction to Arm Compiler 6 1.1 armclang 1.2 armasm 1.3 armlink 1.4 armar 1.5 fromelf 1.6 Arm C libraries 1.7 Arm C libraries 1,8 Application development ,ARM程序开发流程 2,ARM 编译器 5和ARM 编译器 6的兼容性 3&…

ARM处理器开发详解

目录 第一章 嵌入式系统基础知识(不考)嵌入式系统特点交叉调试调试器 第二章 嵌入式 ARM 技术概论ARM的基本数据类型(不考)选择ARM芯片的一般原则Cortex-A9内核的八种工作模式流水线(不考)寄存器组织程序状…

ARM嵌入式常用开发工具介绍及插画开发流程(更新)

这里接着前边的开发环境的配置说,其实用于开发的话,基本的开发环境已经架构好了,不过由于嵌入式开发环境的特殊性(交叉编译),我们还会用到一些其他的外围工具,这里做简要的说明。并重新介绍一下整个开发环境中&#xf…

ARM介绍

什么是ARM? ARM即可以是一家芯片设计厂商的名字,也可以代表一类微处理器的通称,还可以表示为一种技术的名称(这个问题面试的时候可能问道) 1、ARM是一个公司:Advanced RISC Machine Acorn RISC Machi…

《 Arm Compiler 5.06 》__ARM编译器官网下载、安装和使用说明(小白也能懂)

目录 一、前言 二、官方网站下载 三、编译器安装在 Keil 软件上 四、Keil选择编译器V5 “ V5.06 update 7(build 960) ” 五、测试 六、我的资源 (* ̄︶ ̄)创作不易!期待你们的 点赞、收藏和评论喔。 一、前言 Keil MDK-Arm5.37不再默认…