序言
在开发布料展示小程序的过程中,我遇到一个极具挑战性的问题:用户上传的高清图片动辄 20MB+,导致加载缓慢、内存飙升,服务器频繁崩溃。
尝试过使用 WebP 格式压缩,但文件依旧庞大;自己手动压缩图像,也容易引发严重失真。最终,我设计并落地了一套高效、稳定的自适应二阶段压缩算法,结合 线程池+信号量限流机制、软引用优化内存使用,实现了:
✅ 图片体积从 20MB 减至 100KB
✅ 画质几乎无损
✅ 并发场景下系统稳定运行
本文将完整拆解这一方案的实现原理与关键代码,适合有图片上传需求或系统并发压力的开发者参考。
下图展示了初版压缩算法的效果对比,可以清晰看到压缩后的图像质量差异很大。
图片压缩上传核心代码实现
核心模块实现
1. 引入必要依赖(pom.xml)
使用
Thumbnailator
作为图像处理库,结合lombok
简化实体类开发。
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.14</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
2. 配置线程池与信号量(防止并发崩溃)
限制并发处理数,避免大量图片上传造成内存爆炸。
@Configuration
public class FileProcessingConfig {
@Value("${file.processing.queue-capacity:10}")
private int queueCapacity;
@Bean
public ThreadPoolExecutor fileProcessingExecutor() {
int processors = Math.min(Runtime.getRuntime().availableProcessors(), 3);
return new ThreadPoolExecutor(
processors, // 核心线程数
processors, // 最大线程数
60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(queueCapacity),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
@Bean
public Semaphore fileProcessingSemaphore() {
int processors = Math.min(Runtime.getRuntime().availableProcessors(), 3);
return new Semaphore(processors);
}
}
3. 图片压缩工具类
在图片压缩方面,我设计了一套高性能图像处理方案,其核心是"自适应二阶段压缩算法",它能将20MB的高清图片压缩至约100KB,同时保持视觉质量不明显下降。这个算法主要是通过计算初始压缩质量并在需要时进行精确的二次质量调整,实现了压缩率与画质的最佳平衡。
此外,在系统中还采用了两项关键优化技术:
软引用(SoftReference)内存管理机制,有效防止大图像处理时的内存溢出
基于线程池与信号量的并发控制策略,确保高并发场景下的系统稳定性
ImageCompressor 类是整个系统的核心,它提供了同步和异步两种压缩模式,通过CompletableFuture实现非阻塞处理。压缩过程分两个阶段执行:首先进行尺寸调整和初步质量压缩;若结果仍超出目标大小,则使用平方根函数精确计算第二阶段的质量参数,实现更精细的体积控制。
@Slf4j
@Component
public class ImageCompressor {
private static final int TARGET_SIZE = 100 * 1024; // 目标大小100KB
private static final double INITIAL_QUALITY = 0.90; // 初始质量90%
private static final double MIN_QUALITY = 0.65; // 最低质量65%
private