资深架构师亲授Java性能优化技巧,助程序性能飞升

作为深耕Java领域15年的资深架构师,我见证了太多因性能问题导致的系统崩溃。今天我将分享10个经过千锤百炼的性能优化技巧,让你的程序性能实现质的飞跃!

1. 字符串拼接:用告别“+”号

错误示范:

String result = "";
for (int i = 0; i < 10000; i++) {
    result += "data" + i; // 每次循环都创建新对象!
}

优化方案:

StringBuilder sb = new StringBuilder(50000); // 预设容量
for (int i = 0; i < 10000; i++) {
    sb.append("data").append(i);
}
String result = sb.toString();

效果: 万次拼接性能提升50倍!

2. 集合初始化:给一个合适的容量

错误示范:

Map map = new HashMap(); // 默认16,很快需要扩容
for (int i = 0; i < 1000; i++) {
    map.put("key" + i, "value" + i);
}

优化方案:

// 预计算容量:元素数 / 0.75 + 1
Map map = new HashMap(1334);
for (int i = 0; i < 1000; i++) {
    map.put("key" + i, "value" + i);
}

效果: 避免多次扩容,万次put性能提升3倍!

3. 正则表达式:预编译对象

错误示范:

// 每次调用都重新编译
for (String input : inputList) {
    if (input.matches("^\d{4}-\d{2}-\d{2}#34;)) { // 每次都编译!
        // ...
    }
}

优化方案:

private static final Pattern DATE_PATTERN = 
    Pattern.compile("^\d{4}-\d{2}-\d{2}#34;);
for (String input : inputList) {
    if (DATE_PATTERN.matcher(input).matches()) { // 复用已编译对象
        // ...
    }
}

效果: 万次匹配性能提升10倍!

4. 自动装箱:警惕隐式对象创建

错误示范:

Long sum = 0L; // 自动装箱为Long对象
for (long i = 0; i < Integer.MAX_VALUE; i++) {
    sum += i; // 每次循环都创建新Long对象!
}

优化方案:

long sum = 0L; // 使用基本类型
for (long i = 0; i < Integer.MAX_VALUE; i++) {
    sum += i; // 直接操作基本类型
}

效果: 亿次累加内存减少95%!

5. 数据库连接:用好连接池参数

错误配置:

// HikariCP默认配置可能不适用高并发
HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(10); // 并发高时排队等待

优化配置:

HikariConfig config = new HikariConfig();
config.setMaximumPoolSize(50); // 根据业务调整
config.setMinimumIdle(10);     // 保持最小连接
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);
config.setConnectionTestQuery("SELECT 1");

效果: 高并发下数据库响应时间降低80%!

6. 日志输出:用占位符替代字符串拼接

错误示范:

log.debug("User " + userId + " accessed " + resource); // 即使不输出也执行拼接

优化方案:

log.debug("User {} accessed {}", userId, resource); // 延迟拼接

进阶优化:

if (log.isDebugEnabled()) { // 预先判断级别
    log.debug("User {} accessed {}", userId, resource);
}

效果: 日志模块性能提升5倍!

7. 反射调用:缓存对象

错误示范:

// 每次调用都获取Method
for (int i = 0; i < 10000; i++) {
    Method method = obj.getClass().getMethod("process");
    method.invoke(obj);
}

优化方案:

// 缓存Method对象
Method method = obj.getClass().getMethod("process");
for (int i = 0; i < 10000; i++) {
    method.invoke(obj);
}

最佳实践:

// 使用预编译的字节码增强(如CGLIB)
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Service.class);
enhancer.setCallback(new MethodInterceptor() {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
        return proxy.invokeSuper(obj, args); // 直接调用,无反射开销
    }
});

效果: 反射调用性能提升100倍!

8. API:合理选择并行流

错误示范:

List list = new ArrayList();
// 小数据量使用并行流反而更慢
list.parallelStream().map(x -> x * 2).collect(Collectors.toList());

优化方案:

List list = new ArrayList();
// 大数据量(>10000)才用并行流
if (list.size() > 10000) {
    list.parallelStream().map(x -> x * 2).collect(Collectors.toList());
} else {
    list.stream().map(x -> x * 2).collect(Collectors.toList());
}

效果: 大数据处理性能提升3-8倍!

9. 对象复用:避免频繁创建短命对象

错误示范:

public void processRequest(HttpRequest request) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 每次调用都创建
    String date = sdf.format(new Date());
    // ...
}

优化方案:

// 使用ThreadLocal避免线程安全问题
private static final ThreadLocal DATE_FORMATTER =
    ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
public void processRequest(HttpRequest request) {
    String date = DATE_FORMATTER.get().format(new Date()); // 复用对象
    // ...
}

替代方案:

// Java 8推荐使用DateTimeFormatter
private static final DateTimeFormatter FORMATTER = 
    DateTimeFormatter.ofPattern("yyyy-MM-dd");
String date = LocalDate.now().format(FORMATTER); // 线程安全且高效

效果: 高频调用下性能提升20倍!

10. JVM参数调优:针对性设置GC策略

通用配置:

# 生产环境推荐配置
-Xms4g -Xmx4g           # 堆内存固定,避免动态调整
-XX:+UseG1GC           # G1垃圾收集器
-XX:MaxGCPauseMillis=200 # 目标暂停时间
-XX:InitiatingHeapOccupancyPercent=35 # 触发GC的堆占用比
-XX:+UseStringDeduplication # 字符串去重
-XX:+PrintGCDetails -Xloggc:/path/to/gc.log # GC日志

内存分析工具使用:

// 添加JVM参数获取内存dump
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/path/to/dump.hprof
// 使用jcmd分析
jcmd  GC.heap_dump /path/to/dump.hprof

效果: 合理配置可减少Full GC 90%以上!

总结

性能优化不是炫技,而是基于数据和场景的理性选择。记住这三点:

测量优先:用JMH做基准测试,用分析瓶颈权衡利弊:空间换时间,可读性换性能渐进优化:80%的性能问题来自20%的代码

最后送上我的调优箴言:“不要过早优化,但要时时关注性能指标”。优化之路永无止境,但掌握这些核心技巧,你已能解决90%的常见性能问题!

立即行动,用、jmap、等工具分析你的应用,从今天开始写出高性能的Java代码!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注