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

Java开发中那些可以提升性能/效率的小技巧(持续更新)

文章目录

  • 一、Java基础
    • 1、使用反射时做好缓存
    • 2、public类型的Method尽量也setAccessible(true)
    • 3、不要在方法级别使用Class.forName

一、Java基础

1、使用反射时做好缓存

日常开发中,经常会用到反射,尤其是SpringAOP或者其他场景,但是经常会忽略其性能,反射的性能确实比普通的方法性能差很多。

下面是我们日常开发时使用反射的示例,100W次执行需要280毫秒:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;public class Test {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {Test test = new Test();Date start = new Date();for (int i = 0; i < 1000000; i++) {Method test1 = Test.class.getDeclaredMethod("test1", String.class);Object invoke = test1.invoke(test, "123");}System.out.println(new Date().getTime() - start.getTime()); // 280}public void test1(String param) {int i = 0;i ++;}
}

加上Map缓存,我们查看一下性能:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;public class Test {private static Map<String, Method> map = new ConcurrentHashMap<>();public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {Test test = new Test();Date start = new Date();for (int i = 0; i < 1000000; i++) {// Map缓存Method test1 = map.computeIfAbsent(Test.class.getName() + "test1", k -> {try {return Test.class.getDeclaredMethod("test1", String.class);} catch (NoSuchMethodException e) {e.printStackTrace();}return null;});Object invoke = test1.invoke(test, "123");}System.out.println(new Date().getTime() - start.getTime()); // 140}public void test1(String param) {int i = 0;i ++;}
}

前后经过对比,280ms和140ms,能差一倍的性能!

但是,这是100万次反射获取方法,280毫秒其实对于一般系统来说也影响不大了,如果是追求极致的并发,或许可以考虑一下为反射添加缓存。

2、public类型的Method尽量也setAccessible(true)

setAccessible可以将方法、字段的检查设置为true(跳过检查),默认是false(需要进行检查,既private、protected等检查)。

相当于将java.lang.reflect.AccessibleObject中override字段设置为true了:
在这里插入图片描述

如果通过反射调用方法时,需要进行override字段的校验,而这段代码中包含了不少的反射逻辑及native方法调用:
在这里插入图片描述

日常开发中,以及某些Spring的代码中,对于字段或者方法设置Access时,public类型的就不进行setAccessible(true)的操作了,当然这对于最终的结果并没有影响,但是最好是全都进行setAccessible(true)的操作,这会跳过一大段检查的逻辑:
org.springframework.util.ReflectionUtils#makeAccessible(java.lang.reflect.Constructor<?>)
在这里插入图片描述
建议去掉判断,直接进行setAccessible(true)的操作,不管类是否是public的、不管方法和字段是public的。

3、不要在方法级别使用Class.forName

调用Class.forName方法时,会执行Classloader的loadClass方法,这个方法是带着synchronized的
在这里插入图片描述
所以,在并发情况下,会有锁竞争的场景,比如说Spring中的依赖注入,为了检查Inject类是否存在,在构造方法中做了检查。当然这里也不会有什么并发问题,该构造方法也只会调用一次。
在这里插入图片描述
正确的方法是在static块中进行调用:
在这里插入图片描述


http://www.mrgr.cn/news/34619.html

相关文章:

  • [leetcode刷题]面试经典150题之6轮转数字(简单)
  • 文件服务器FastDFS 消息队列中间件RabbitMQ
  • C++_23_STL容器
  • 孙子兵法及三十六计学习笔记
  • css如何设置间距
  • vue3基础九问,你会几问
  • 使用Docker一键部署Blossom笔记软件
  • 快速搭建Kubernetes集群
  • 选择排序(C语言实现)
  • spring 的启动过程
  • 快手旗下——Kolors模型部署与使用指南
  • Python中的文件读取艺术:从新手到高手的全面指南
  • CVC输入语言
  • 人工智能之计算机视觉的发展历程与相关技术内容,相应的模型介绍
  • 10个降低性能的SQL问题及改进措施
  • RK3568笔记六十二:使用V4L2读取摄像头并在LCD上显示
  • 5. 条件 Conditionals
  • 每日一练:二叉树的直径
  • matlab之数据处理:滑动平均滤波算法与五点三次平滑算法
  • 828华为云征文 | 将Vue项目部署到Flexus云服务器X实例并实现公网访问