feat(puzzle): 使用虚拟线程优化拼图模板批量生成性能

- 将原有的串行模板生成逻辑改为并行处理
- 使用虚拟线程池提升高并发场景下的执行效率
- 通过 CompletableFuture 异步执行每个模板的生成任务
- 保留原有日志记录和异常处理机制
- 统计成功与失败数量并输出汇总日志
This commit is contained in:
2025-12-13 17:38:48 +08:00
parent 83d1096fdb
commit dbee1d9709
2 changed files with 61 additions and 43 deletions

View File

@@ -74,22 +74,31 @@ public class PuzzleGenerationOrchestrator {
// 3. 准备公共动态数据 // 3. 准备公共动态数据
Map<String, String> baseDynamicData = buildBaseDynamicData(faceId, faceUrl, scenicBasic); Map<String, String> baseDynamicData = buildBaseDynamicData(faceId, faceUrl, scenicBasic);
// 4. 遍历所有模板,逐个生成 // 4. 使用虚拟线程池并行生成所有模板
int successCount = 0; java.util.concurrent.atomic.AtomicInteger successCount = new java.util.concurrent.atomic.AtomicInteger(0);
int failCount = 0; java.util.concurrent.atomic.AtomicInteger failCount = new java.util.concurrent.atomic.AtomicInteger(0);
for (PuzzleTemplateDTO template : templateList) {
try (java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor()) {
// 为每个模板创建一个异步任务
List<java.util.concurrent.CompletableFuture<Void>> futures = templateList.stream()
.map(template -> java.util.concurrent.CompletableFuture.runAsync(() -> {
try { try {
generateSingleTemplate(scenicId, faceId, memberId, template, baseDynamicData); generateSingleTemplate(scenicId, faceId, memberId, template, baseDynamicData);
successCount++; successCount.incrementAndGet();
} catch (Exception e) { } catch (Exception e) {
log.error("拼图生成失败: scenicId={}, templateCode={}, templateName={}", log.error("拼图生成失败: scenicId={}, templateCode={}, templateName={}",
scenicId, template.getCode(), template.getName(), e); scenicId, template.getCode(), template.getName(), e);
failCount++; failCount.incrementAndGet();
} }
}, executor))
.toList();
// 等待所有任务完成
java.util.concurrent.CompletableFuture.allOf(futures.toArray(new java.util.concurrent.CompletableFuture[0])).join();
} }
log.info("景区拼图模板批量生成完成: scenicId={}, 总数={}, 成功={}, 失败={}", log.info("景区拼图模板批量生成完成: scenicId={}, 总数={}, 成功={}, 失败={}",
scenicId, templateList.size(), successCount, failCount); scenicId, templateList.size(), successCount.get(), failCount.get());
} catch (Exception e) { } catch (Exception e) {
// 异步任务失败不影响主流程,仅记录日志 // 异步任务失败不影响主流程,仅记录日志

View File

@@ -390,10 +390,14 @@ public class FaceMatchingOrchestrator {
baseDynamicData.put("scenicText", scenicBasic.getName()); baseDynamicData.put("scenicText", scenicBasic.getName());
baseDynamicData.put("dateStr", DateUtil.format(new Date(), "yyyy.MM.dd")); baseDynamicData.put("dateStr", DateUtil.format(new Date(), "yyyy.MM.dd"));
// 遍历所有模板,逐个生成 // 使用虚拟线程池并行生成所有模板
int successCount = 0; java.util.concurrent.atomic.AtomicInteger successCount = new java.util.concurrent.atomic.AtomicInteger(0);
int failCount = 0; java.util.concurrent.atomic.AtomicInteger failCount = new java.util.concurrent.atomic.AtomicInteger(0);
for (PuzzleTemplateDTO template : templateList) {
try (java.util.concurrent.ExecutorService executor = java.util.concurrent.Executors.newVirtualThreadPerTaskExecutor()) {
// 为每个模板创建一个异步任务
List<java.util.concurrent.CompletableFuture<Void>> futures = templateList.stream()
.map(template -> java.util.concurrent.CompletableFuture.runAsync(() -> {
try { try {
log.info("开始生成拼图: scenicId={}, templateCode={}, templateName={}", log.info("开始生成拼图: scenicId={}, templateCode={}, templateName={}",
scenicId, template.getCode(), template.getName()); scenicId, template.getCode(), template.getName());
@@ -415,17 +419,22 @@ public class FaceMatchingOrchestrator {
log.info("拼图生成成功: scenicId={}, templateCode={}, imageUrl={}", log.info("拼图生成成功: scenicId={}, templateCode={}, imageUrl={}",
scenicId, template.getCode(), response.getImageUrl()); scenicId, template.getCode(), response.getImageUrl());
successCount++; successCount.incrementAndGet();
} catch (Exception e) { } catch (Exception e) {
log.error("拼图生成失败: scenicId={}, templateCode={}, templateName={}", log.error("拼图生成失败: scenicId={}, templateCode={}, templateName={}",
scenicId, template.getCode(), template.getName(), e); scenicId, template.getCode(), template.getName(), e);
failCount++; failCount.incrementAndGet();
} }
}, executor))
.toList();
// 等待所有任务完成
java.util.concurrent.CompletableFuture.allOf(futures.toArray(new java.util.concurrent.CompletableFuture[0])).join();
} }
log.info("景区拼图模板批量生成完成: scenicId={}, 总数={}, 成功={}, 失败={}", log.info("景区拼图模板批量生成完成: scenicId={}, 总数={}, 成功={}, 失败={}",
scenicId, templateList.size(), successCount, failCount); scenicId, templateList.size(), successCount.get(), failCount.get());
} catch (Exception e) { } catch (Exception e) {
// 异步任务失败不影响主流程,仅记录日志 // 异步任务失败不影响主流程,仅记录日志