From 21916716bf3c3d4198e6766b5fd51e4a08b5c4e0 Mon Sep 17 00:00:00 2001 From: HeungTak Lee Date: Fri, 6 Feb 2026 13:37:17 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20CancellableQueryManager=EC=9D=98=20Cache?= =?UTF-8?q?dThreadPool=EC=9D=84=20=EC=A0=9C=ED=95=9C=EB=90=9C=20ThreadPool?= =?UTF-8?q?Executor=EB=A1=9C=20=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1.3: 무제한 스레드 생성 방지 - newCachedThreadPool → ThreadPoolExecutor(core:5, max:20, queue:100) - CallerRunsPolicy 적용으로 큐 포화 시 자연 백프레셔 - 부하 시 무제한 스레드 생성으로 인한 OOM/컨텍스트 스위칭 오버헤드 방지 Co-Authored-By: Claude Opus 4.6 --- .../query/CancellableQueryManager.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/gc/mda/signal_batch/domain/vessel/service/query/CancellableQueryManager.java b/src/main/java/gc/mda/signal_batch/domain/vessel/service/query/CancellableQueryManager.java index 2cceb23..22e9614 100644 --- a/src/main/java/gc/mda/signal_batch/domain/vessel/service/query/CancellableQueryManager.java +++ b/src/main/java/gc/mda/signal_batch/domain/vessel/service/query/CancellableQueryManager.java @@ -20,13 +20,20 @@ public class CancellableQueryManager { // 활성 쿼리 컨텍스트 관리 private final Map activeQueries = new ConcurrentHashMap<>(); - // 쿼리 실행을 위한 스레드 풀 - private final ExecutorService queryExecutor = Executors.newCachedThreadPool(r -> { - Thread thread = new Thread(r); - thread.setName("query-executor-" + thread.getId()); - thread.setDaemon(true); - return thread; - }); + // 쿼리 실행을 위한 스레드 풀 (상한 제한) + private final ExecutorService queryExecutor = new ThreadPoolExecutor( + 5, // corePoolSize + 20, // maximumPoolSize (무제한 방지) + 60L, TimeUnit.SECONDS, // keepAliveTime + new LinkedBlockingQueue<>(100), // 대기 큐 크기 제한 + r -> { + Thread thread = new Thread(r); + thread.setName("query-executor-" + thread.getId()); + thread.setDaemon(true); + return thread; + }, + new ThreadPoolExecutor.CallerRunsPolicy() // 큐 포화 시 호출 스레드에서 실행 + ); /** * 취소 가능한 쿼리 실행