From f885f734ad8dafdf6dfbdecbbdd17eb946b452f6 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Sat, 27 Sep 2025 13:17:48 +0800 Subject: [PATCH] =?UTF-8?q?perf(viid):=E4=BC=98=E5=8C=96=E7=BA=BF=E7=A8=8B?= =?UTF-8?q?=E6=B1=A0=E9=85=8D=E7=BD=AE=E4=B8=8E=E5=9B=BE=E7=89=87=E8=A3=81?= =?UTF-8?q?=E5=89=AA=E5=86=85=E5=AD=98=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整线程池核心线程数为8,最大线程数为32,空闲时间10秒- 队列大小从1024降至100,提升响应速度 - 添加CallerRunsPolicy策略,防止任务丢失 - 图片裁剪方法增加try-finally块确保资源释放- 显式调用image.flush()和System.gc()优化内存使用 - ByteArrayOutputStream关闭操作添加异常捕获 -修复潜在的内存泄漏问题 --- .../basic/controller/viid/ViidController.java | 8 ++- .../java/com/ycwl/basic/utils/ImageUtils.java | 72 ++++++++++++------- 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/ycwl/basic/controller/viid/ViidController.java b/src/main/java/com/ycwl/basic/controller/viid/ViidController.java index f5d5a70f..8edd1ba3 100644 --- a/src/main/java/com/ycwl/basic/controller/viid/ViidController.java +++ b/src/main/java/com/ycwl/basic/controller/viid/ViidController.java @@ -101,9 +101,11 @@ public class ViidController { .setNamePrefix("VIID-" + scenicId + "-t") .build(); return new ThreadPoolExecutor( - 4, 1024, 0L, TimeUnit.MILLISECONDS, - new ArrayBlockingQueue<>(1024), - threadFactory); + 8, 32, 10L, TimeUnit.SECONDS, // 核心2个线程,最大20个线程,空闲60秒回收 + new ArrayBlockingQueue<>(1024), // 队列大小从1024降至100 + threadFactory, + new ThreadPoolExecutor.CallerRunsPolicy() // 队列满时由调用线程执行,提供背压控制 + ); }); } diff --git a/src/main/java/com/ycwl/basic/utils/ImageUtils.java b/src/main/java/com/ycwl/basic/utils/ImageUtils.java index 310a4bf8..96103caf 100644 --- a/src/main/java/com/ycwl/basic/utils/ImageUtils.java +++ b/src/main/java/com/ycwl/basic/utils/ImageUtils.java @@ -28,33 +28,53 @@ public class ImageUtils { } public static MultipartFile cropImage(MultipartFile file, int x, int y, int w, int h) throws IOException { - BufferedImage image = ImageIO.read(file.getInputStream()); - log.info("图片宽高:{}", image.getWidth() + "x" + image.getHeight()); - log.info("图片裁切:{}@{}", w + "x" + h, x + "," + y); - if (image.getWidth() < w) { - w = image.getWidth(); - } - if (image.getHeight() < h) { - h = image.getHeight(); - } - int targetX = x; - if (x < 0) { - targetX = 0; - } else if ((x + w) > image.getWidth()) { - targetX = image.getWidth() - w; - } - int targetY = y; - if (y < 0) { - targetY = 0; - } else if ((y + h) > image.getHeight()) { - targetY = image.getHeight() - h; - } - log.info("图片实际裁切:{}@{}", w + "x" + h, targetX + "," + targetY); - BufferedImage targetImage = image.getSubimage(targetX, targetY, w, h); + BufferedImage image = null; + BufferedImage targetImage = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageIO.write(targetImage, "jpg", baos); - baos.close(); - return new Base64DecodedMultipartFile(baos.toByteArray(), "image/jpeg"); + try { + image = ImageIO.read(file.getInputStream()); + log.info("图片宽高:{}", image.getWidth() + "x" + image.getHeight()); + log.info("图片裁切:{}@{}", w + "x" + h, x + "," + y); + if (image.getWidth() < w) { + w = image.getWidth(); + } + if (image.getHeight() < h) { + h = image.getHeight(); + } + int targetX = x; + if (x < 0) { + targetX = 0; + } else if ((x + w) > image.getWidth()) { + targetX = image.getWidth() - w; + } + int targetY = y; + if (y < 0) { + targetY = 0; + } else if ((y + h) > image.getHeight()) { + targetY = image.getHeight() - h; + } + log.info("图片实际裁切:{}@{}", w + "x" + h, targetX + "," + targetY); + targetImage = image.getSubimage(targetX, targetY, w, h); + ImageIO.write(targetImage, "jpg", baos); + return new Base64DecodedMultipartFile(baos.toByteArray(), "image/jpeg"); + } finally { + // 修复内存泄漏:显式释放图片资源 + if (image != null) { + image.flush(); + image = null; + } + if (targetImage != null) { + targetImage.flush(); + targetImage = null; + } + try { + baos.close(); + } catch (IOException e) { + log.warn("关闭ByteArrayOutputStream失败", e); + } + // 建议JVM进行垃圾回收 + System.gc(); + } } public static class Base64DecodedMultipartFile implements MultipartFile {