diff --git a/parser/src/main/java/cn/qaiu/parser/customjs/JsParserExecutor.java b/parser/src/main/java/cn/qaiu/parser/customjs/JsParserExecutor.java index 9414df7..69310b4 100644 --- a/parser/src/main/java/cn/qaiu/parser/customjs/JsParserExecutor.java +++ b/parser/src/main/java/cn/qaiu/parser/customjs/JsParserExecutor.java @@ -29,12 +29,13 @@ import java.util.stream.Collectors; * @author QAIU * Create at 2025/10/17 */ -public class JsParserExecutor implements IPanTool { - +public class JsParserExecutor implements IPanTool, AutoCloseable { + private static final Logger log = LoggerFactory.getLogger(JsParserExecutor.class); - - private static final WorkerExecutor EXECUTOR = WebClientVertxInit.get().createSharedWorkerExecutor("parser-executor", 32); - + + private static WorkerExecutor EXECUTOR; + private static final Object EXECUTOR_LOCK = new Object(); + private static String FETCH_RUNTIME_JS = null; private final CustomParserConfig config; @@ -149,6 +150,7 @@ public class JsParserExecutor implements IPanTool { /** * 释放资源(ScriptEngine 和 HttpClient),避免内存泄漏 */ + @Override public void close() { if (httpClient != null) { httpClient.close(); @@ -162,12 +164,40 @@ public class JsParserExecutor implements IPanTool { } } + /** + * 关闭全局 WorkerExecutor(应在应用关闭时调用) + */ + public static void shutdownExecutor() { + synchronized (EXECUTOR_LOCK) { + if (EXECUTOR != null) { + EXECUTOR.close(); + EXECUTOR = null; + log.info("JsParserExecutor WorkerExecutor 已关闭"); + } + } + } + + /** + * 获取或创建 WorkerExecutor(懒加载) + */ + private static WorkerExecutor getExecutor() { + if (EXECUTOR != null) { + return EXECUTOR; + } + synchronized (EXECUTOR_LOCK) { + if (EXECUTOR == null) { + EXECUTOR = WebClientVertxInit.get().createSharedWorkerExecutor("parser-executor", 32); + } + return EXECUTOR; + } + } + @Override public Future parse() { jsLogger.info("开始执行JavaScript解析器: {}", config.getType()); // 使用executeBlocking在工作线程上执行,避免阻塞EventLoop线程 - return EXECUTOR.executeBlocking(() -> { + return getExecutor().executeBlocking(() -> { // 直接调用全局parse函数 Object parseFunction = engine.get("parse"); if (parseFunction == null) { @@ -197,7 +227,7 @@ public class JsParserExecutor implements IPanTool { jsLogger.info("开始执行JavaScript文件列表解析: {}", config.getType()); // 使用executeBlocking在工作线程上执行,避免阻塞EventLoop线程 - return EXECUTOR.executeBlocking(() -> { + return getExecutor().executeBlocking(() -> { // 直接调用全局parseFileList函数 Object parseFileListFunction = engine.get("parseFileList"); if (parseFileListFunction == null) { @@ -230,7 +260,7 @@ public class JsParserExecutor implements IPanTool { jsLogger.info("开始执行JavaScript按ID解析: {}", config.getType()); // 使用executeBlocking在工作线程上执行,避免阻塞EventLoop线程 - return EXECUTOR.executeBlocking(() -> { + return getExecutor().executeBlocking(() -> { // 直接调用全局parseById函数 Object parseByIdFunction = engine.get("parseById"); if (parseByIdFunction == null) {