diff --git a/src/main/java/com/ycwl/basic/face/pipeline/helper/PuzzleGenerationOrchestrator.java b/src/main/java/com/ycwl/basic/face/pipeline/helper/PuzzleGenerationOrchestrator.java index 081d0dcc..ac8e9180 100644 --- a/src/main/java/com/ycwl/basic/face/pipeline/helper/PuzzleGenerationOrchestrator.java +++ b/src/main/java/com/ycwl/basic/face/pipeline/helper/PuzzleGenerationOrchestrator.java @@ -74,22 +74,31 @@ public class PuzzleGenerationOrchestrator { // 3. 准备公共动态数据 Map baseDynamicData = buildBaseDynamicData(faceId, faceUrl, scenicBasic); - // 4. 遍历所有模板,逐个生成 - int successCount = 0; - int failCount = 0; - for (PuzzleTemplateDTO template : templateList) { - try { - generateSingleTemplate(scenicId, faceId, memberId, template, baseDynamicData); - successCount++; - } catch (Exception e) { - log.error("拼图生成失败: scenicId={}, templateCode={}, templateName={}", - scenicId, template.getCode(), template.getName(), e); - failCount++; - } + // 4. 使用虚拟线程池并行生成所有模板 + java.util.concurrent.atomic.AtomicInteger successCount = new java.util.concurrent.atomic.AtomicInteger(0); + java.util.concurrent.atomic.AtomicInteger failCount = new java.util.concurrent.atomic.AtomicInteger(0); + + try (java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor()) { + // 为每个模板创建一个异步任务 + List> futures = templateList.stream() + .map(template -> java.util.concurrent.CompletableFuture.runAsync(() -> { + try { + generateSingleTemplate(scenicId, faceId, memberId, template, baseDynamicData); + successCount.incrementAndGet(); + } catch (Exception e) { + log.error("拼图生成失败: scenicId={}, templateCode={}, templateName={}", + scenicId, template.getCode(), template.getName(), e); + failCount.incrementAndGet(); + } + }, executor)) + .toList(); + + // 等待所有任务完成 + java.util.concurrent.CompletableFuture.allOf(futures.toArray(new java.util.concurrent.CompletableFuture[0])).join(); } log.info("景区拼图模板批量生成完成: scenicId={}, 总数={}, 成功={}, 失败={}", - scenicId, templateList.size(), successCount, failCount); + scenicId, templateList.size(), successCount.get(), failCount.get()); } catch (Exception e) { // 异步任务失败不影响主流程,仅记录日志 diff --git a/src/main/java/com/ycwl/basic/service/pc/orchestrator/FaceMatchingOrchestrator.java b/src/main/java/com/ycwl/basic/service/pc/orchestrator/FaceMatchingOrchestrator.java index 6c21cacf..612783e1 100644 --- a/src/main/java/com/ycwl/basic/service/pc/orchestrator/FaceMatchingOrchestrator.java +++ b/src/main/java/com/ycwl/basic/service/pc/orchestrator/FaceMatchingOrchestrator.java @@ -390,42 +390,51 @@ public class FaceMatchingOrchestrator { baseDynamicData.put("scenicText", scenicBasic.getName()); baseDynamicData.put("dateStr", DateUtil.format(new Date(), "yyyy.MM.dd")); - // 遍历所有模板,逐个生成 - int successCount = 0; - int failCount = 0; - for (PuzzleTemplateDTO template : templateList) { - try { - log.info("开始生成拼图: scenicId={}, templateCode={}, templateName={}", - scenicId, template.getCode(), template.getName()); + // 使用虚拟线程池并行生成所有模板 + java.util.concurrent.atomic.AtomicInteger successCount = new java.util.concurrent.atomic.AtomicInteger(0); + java.util.concurrent.atomic.AtomicInteger failCount = new java.util.concurrent.atomic.AtomicInteger(0); - // 构建生成请求 - PuzzleGenerateRequest generateRequest = new PuzzleGenerateRequest(); - generateRequest.setScenicId(scenicId); - generateRequest.setUserId(memberId); - generateRequest.setFaceId(faceId); - generateRequest.setBusinessType("face_matching"); - generateRequest.setTemplateCode(template.getCode()); - generateRequest.setOutputFormat("PNG"); - generateRequest.setQuality(90); - generateRequest.setDynamicData(new HashMap<>(baseDynamicData)); - generateRequest.setRequireRuleMatch(true); + try (java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor()) { + // 为每个模板创建一个异步任务 + List> futures = templateList.stream() + .map(template -> java.util.concurrent.CompletableFuture.runAsync(() -> { + try { + log.info("开始生成拼图: scenicId={}, templateCode={}, templateName={}", + scenicId, template.getCode(), template.getName()); - // 调用拼图生成服务 - PuzzleGenerateResponse response = puzzleGenerateService.generate(generateRequest); + // 构建生成请求 + PuzzleGenerateRequest generateRequest = new PuzzleGenerateRequest(); + generateRequest.setScenicId(scenicId); + generateRequest.setUserId(memberId); + generateRequest.setFaceId(faceId); + generateRequest.setBusinessType("face_matching"); + generateRequest.setTemplateCode(template.getCode()); + generateRequest.setOutputFormat("PNG"); + generateRequest.setQuality(90); + generateRequest.setDynamicData(new HashMap<>(baseDynamicData)); + generateRequest.setRequireRuleMatch(true); - log.info("拼图生成成功: scenicId={}, templateCode={}, imageUrl={}", - scenicId, template.getCode(), response.getImageUrl()); - successCount++; + // 调用拼图生成服务 + PuzzleGenerateResponse response = puzzleGenerateService.generate(generateRequest); - } catch (Exception e) { - log.error("拼图生成失败: scenicId={}, templateCode={}, templateName={}", - scenicId, template.getCode(), template.getName(), e); - failCount++; - } + log.info("拼图生成成功: scenicId={}, templateCode={}, imageUrl={}", + scenicId, template.getCode(), response.getImageUrl()); + successCount.incrementAndGet(); + + } catch (Exception e) { + log.error("拼图生成失败: scenicId={}, templateCode={}, templateName={}", + scenicId, template.getCode(), template.getName(), e); + failCount.incrementAndGet(); + } + }, executor)) + .toList(); + + // 等待所有任务完成 + java.util.concurrent.CompletableFuture.allOf(futures.toArray(new java.util.concurrent.CompletableFuture[0])).join(); } - log.info("景区拼图模板批量生成完成: scenicId={}, 总数={}, 成功={}, 失败={}", - scenicId, templateList.size(), successCount, failCount); + log.info("景区拼图模板批量生成完成: scenicId={}, 总数={}, 成功={}, 失败={}", + scenicId, templateList.size(), successCount.get(), failCount.get()); } catch (Exception e) { // 异步任务失败不影响主流程,仅记录日志