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 {