优化策略及原理
- 使用线程池控制并发度:通过创建固定大小的线程池来执行
CompletableFuture
任务。这样可以限制同时执行的任务数量,避免过多任务同时竞争系统资源,从而防止资源耗尽。例如,数据库连接数有限时,过多任务同时尝试获取连接会导致连接池耗尽。
- 资源管理:在
thenAccept
中进行资源的合理管理,比如及时释放数据库连接等资源,避免资源长时间被占用。
关键代码示例
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class CompletableFutureOptimization {
private static final ExecutorService executorService = Executors.newFixedThreadPool(10);
private static final AtomicInteger counter = new AtomicInteger();
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
CompletableFuture.supplyAsync(() -> {
// 模拟任务执行
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
return counter.incrementAndGet();
}, executorService)
.thenAccept(result -> {
// 模拟结果消费和资源管理
System.out.println("Processed result: " + result);
// 例如这里可以添加释放数据库连接等资源管理的代码
});
}
executorService.shutdown();
try {
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
executorService.shutdownNow();
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
System.err.println("Pool did not terminate");
}
}
} catch (InterruptedException ie) {
executorService.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
性能测试思路
- 指标设定:
- 吞吐量:统计单位时间内完成的任务数量,通过记录开始时间和结束时间以及完成的任务总数来计算。
- 响应时间:记录每个任务从提交到完成消费的时间,可通过在任务开始和结束时记录时间戳计算。
- 资源使用率:监控内存、CPU使用率以及数据库连接数等资源的使用情况,例如使用
java.lang.management
包获取内存和CPU信息,数据库连接池提供的监控工具获取连接使用情况。
- 测试场景:
- 不同并发数:从低并发(如10个任务)逐渐增加到高并发(如1000个任务),观察系统在不同并发压力下的性能指标。
- 不同资源限制:例如改变线程池大小、减少数据库连接数等,测试系统在资源受限情况下的性能表现。
- 工具使用:
- JMH(Java Microbenchmark Harness):用于微基准测试,精确测量代码片段的性能。
- JMeter:用于模拟高并发场景,对系统整体性能进行测试。