diff --git a/src/main/java/org/jcnc/jnotepad/LunchApp.java b/src/main/java/org/jcnc/jnotepad/LunchApp.java index 4c5e7a146913958533888d3af1987cdbf9c2f04b..9b16a844cbaa2210016f3d0d4b3658a6d89c945a 100644 --- a/src/main/java/org/jcnc/jnotepad/LunchApp.java +++ b/src/main/java/org/jcnc/jnotepad/LunchApp.java @@ -14,6 +14,7 @@ import org.jcnc.jnotepad.app.init.LoadLanguageConfig; import org.jcnc.jnotepad.app.init.LoadShortcutKeyConfig; import org.jcnc.jnotepad.constants.AppConstants; import org.jcnc.jnotepad.controller.manager.Controller; +import org.jcnc.jnotepad.manager.ThreadPoolManager; import org.jcnc.jnotepad.ui.LineNumberTextArea; import org.jcnc.jnotepad.view.init.View; import org.jcnc.jnotepad.view.manager.ViewManager; @@ -22,7 +23,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; /** @@ -34,7 +34,8 @@ public class LunchApp extends Application { /** * 线程池 */ - private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool(); + private final ExecutorService threadPool = ThreadPoolManager.getThreadPool(); + LocalizationConfig localizationConfig = LocalizationConfig.getLocalizationConfig(); Controller controller = Controller.getInstance(); Scene scene; @@ -71,7 +72,7 @@ public class LunchApp extends Application { // 使用线程池加载关联文件并创建文本区域 List rawParameters = getParameters().getRaw(); - THREAD_POOL.execute(() -> { + threadPool.execute(() -> { LineNumberTextArea textArea = controller.openAssociatedFileAndCreateTextArea(rawParameters); if (!Objects.isNull(textArea)) { Platform.runLater(() -> controller.updateUiWithNewTextArea(textArea)); @@ -92,7 +93,7 @@ public class LunchApp extends Application { @Override public void stop() { // 关闭线程池 - THREAD_POOL.shutdownNow(); + threadPool.shutdownNow(); } public static void main(String[] args) { diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/LocalizationHandler.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/LocalizationHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..5ce1472c2c37e086ca583e7c8c5d0afc0743bfca --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/LocalizationHandler.java @@ -0,0 +1,13 @@ +package org.jcnc.jnotepad.controller.event.handler; + +import javafx.event.ActionEvent; +import javafx.event.EventHandler; + +/** + * 本地化处理抽象类 + * + * @author gewuyou + */ +public abstract class LocalizationHandler implements EventHandler { + +} diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenConfig.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenConfig.java index 51fc8f26795074a53f53ac65eb0f0a5b9c16c65c..6419c4a6ec91ec30c9d9c7752de59c56f274a22b 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenConfig.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenConfig.java @@ -1,8 +1,9 @@ package org.jcnc.jnotepad.controller.event.handler; -import javafx.concurrent.Task; import javafx.event.ActionEvent; +import javafx.event.EventHandler; import org.jcnc.jnotepad.controller.manager.Controller; +import org.jcnc.jnotepad.manager.ThreadPoolManager; import org.jcnc.jnotepad.tool.LogUtil; import java.io.File; @@ -14,19 +15,16 @@ import static org.jcnc.jnotepad.constants.AppConstants.CONFIG_NAME; * * @author gewuyou */ -public class OpenConfig extends OpenHandler { +public class OpenConfig implements EventHandler { + @Override public void handle(ActionEvent actionEvent) { - // 获取控制器 Controller controller = Controller.getInstance(); - // 显示文件选择对话框,并获取选中的文件 + // 显示文件选择对话框,并获取配置文件 File file = new File(CONFIG_NAME); LogUtil.getLogger(this.getClass()).info("已调用打开配置文件功能"); LogUtil.getLogger(this.getClass()).info("{}", file); - // 创建打开文件的任务 - Task openFileTask = getVoidTask(controller, file); - // 创建并启动线程执行任务 - Thread thread = new Thread(openFileTask); - thread.start(); + // 创建打开文件的任务并启动线程执行任务 + ThreadPoolManager.getThreadPool().submit(controller.createOpenFileTask(file)); } } diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java index 651b91bedfa85f9241fb98985dc631648178c307..25128629f51ddfe7642392788cf420412a9e1619 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java +++ b/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenFile.java @@ -1,9 +1,10 @@ package org.jcnc.jnotepad.controller.event.handler; -import javafx.concurrent.Task; import javafx.event.ActionEvent; +import javafx.event.EventHandler; import javafx.stage.FileChooser; import org.jcnc.jnotepad.controller.manager.Controller; +import org.jcnc.jnotepad.manager.ThreadPoolManager; import java.io.File; @@ -15,7 +16,7 @@ import java.io.File; * * @author 许轲 */ -public class OpenFile extends OpenHandler { +public class OpenFile implements EventHandler { /** * 处理打开文件事件。 * @@ -30,11 +31,8 @@ public class OpenFile extends OpenHandler { // 显示文件选择对话框,并获取选中的文件 File file = fileChooser.showOpenDialog(null); if (file != null) { - // 创建打开文件的任务 - Task openFileTask = getVoidTask(controller, file); - // 创建并启动线程执行任务 - Thread thread = new Thread(openFileTask); - thread.start(); + // 创建打开文件的任务并启动线程执行任务 + ThreadPoolManager.getThreadPool().submit(controller.createOpenFileTask(file)); } } } diff --git a/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenHandler.java b/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenHandler.java deleted file mode 100644 index d23c41bcb76ef815ec6d2795ef44d92f5b23cf90..0000000000000000000000000000000000000000 --- a/src/main/java/org/jcnc/jnotepad/controller/event/handler/OpenHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.jcnc.jnotepad.controller.event.handler; - -import javafx.concurrent.Task; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import org.jcnc.jnotepad.controller.manager.Controller; - -import java.io.File; - -/** - * 打开抽象类 - * - * @author gewuyou - */ -public abstract class OpenHandler implements EventHandler { - /** - * 获取空返回值任务 - * - * @param controller 控制器 - * @param file 文件 - * @return javafx.concurrent.Task - * @apiNote - */ - protected Task getVoidTask(Controller controller, File file) { - Task openFileTask = new Task<>() { - @Override - protected Void call() { - // 调用控制器的getText方法,读取文件内容 - controller.getText(file); - return null; - } - }; - - // 设置任务成功完成时的处理逻辑 - openFileTask.setOnSucceeded(e -> { - // 处理成功的逻辑 - }); - - // 设置任务失败时的处理逻辑 - openFileTask.setOnFailed(e -> { - // 处理失败的逻辑 - }); - return openFileTask; - } -} diff --git a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java index 3717a38825bc512262e4bfbe76d2509fdaadf0a0..bd76b8fafbba05f0d6ac5065a323852484d78fc8 100644 --- a/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java +++ b/src/main/java/org/jcnc/jnotepad/controller/manager/Controller.java @@ -4,6 +4,7 @@ import javafx.application.Platform; import javafx.concurrent.Task; import org.jcnc.jnotepad.Interface.ControllerInterface; import org.jcnc.jnotepad.app.config.LocalizationConfig; +import org.jcnc.jnotepad.manager.ThreadPoolManager; import org.jcnc.jnotepad.tool.EncodingDetector; import org.jcnc.jnotepad.tool.LogUtil; import org.jcnc.jnotepad.ui.LineNumberTextArea; @@ -18,6 +19,8 @@ import java.io.IOException; import java.nio.charset.Charset; import java.util.List; +import static org.jcnc.jnotepad.manager.ThreadPoolManager.threadContSelfSubtracting; + /** * 控制器类,实现ControllerInterface接口,用于管理文本编辑器的各种操作和事件处理。 * 包括打开关联文件、创建文本区域、处理行分隔、新建文件、打开文件、自动保存等功能。 @@ -151,14 +154,21 @@ public class Controller implements ControllerInterface { * @param file 文件对象 * @return 打开文件的任务 */ - private Task createOpenFileTask(File file) { - return new Task<>() { + public Task createOpenFileTask(File file) { + Task openFileTask = new Task<>() { @Override protected Void call() { getText(file); return null; } + }; + // 设置任务成功完成时的处理逻辑 + openFileTask.setOnSucceeded(e -> threadContSelfSubtracting()); + + // 设置任务失败时的处理逻辑 + openFileTask.setOnFailed(e -> threadContSelfSubtracting()); + return openFileTask; } /** @@ -167,9 +177,7 @@ public class Controller implements ControllerInterface { * @param file 文件对象 */ private void openFile(File file) { - Task openFileTask = createOpenFileTask(file); - Thread thread = new Thread(openFileTask); - thread.start(); + ThreadPoolManager.getThreadPool().submit(createOpenFileTask(file)); } } diff --git a/src/main/java/org/jcnc/jnotepad/manager/ThreadPoolManager.java b/src/main/java/org/jcnc/jnotepad/manager/ThreadPoolManager.java new file mode 100644 index 0000000000000000000000000000000000000000..b38888140bc9ecbd3d8fe81a26afa00bc2114d6a --- /dev/null +++ b/src/main/java/org/jcnc/jnotepad/manager/ThreadPoolManager.java @@ -0,0 +1,84 @@ +package org.jcnc.jnotepad.manager; + +import org.jcnc.jnotepad.tool.LogUtil; +import org.slf4j.Logger; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 线程池管理类
+ * 项目中所有异步操作建议使用该类进行获取线程执行异步操作 + * + * @author gewuyou + */ +public class ThreadPoolManager { + private ThreadPoolManager() { + } + + private static final Logger logger = LogUtil.getLogger(ThreadPoolManager.class); + /** + * 核心线程数 + */ + private static final int CORE_POOL_SIZE = 2; + /** + * 最大线程数 + */ + private static final int MAXIMUM_POOL_SIZE = 4; + /** + * 空闲线程回收时间间隔 + */ + private static final Long KEEP_ALIVE_TIME = 3L; + /** + * 空闲线程回收时间间隔单位 + */ + private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS; + /** + * 提交任务的队列
+ * 注:
+ * ArrayBlockingQueue:有界带缓冲阻塞队列
+ * SynchronousQueue:无缓冲阻塞队列
+ * LinkedBlockingQueue:无界带缓冲阻塞队列 + */ + private static final BlockingQueue BLOCKING_QUEUE = new LinkedBlockingQueue<>(4); + /** + * 当前线程数 + */ + private static final AtomicInteger THREAD_COUNT = new AtomicInteger(1); + + /** + * 线程数自减 + * + * @apiNote 当你创建任务时,务必在最后执行一次该方法 + * @see ThreadPoolManager + * @since 2023/8/26 22:00 + */ + public static void threadContSelfSubtracting() { + THREAD_COUNT.decrementAndGet(); + } + + /** + * 线程工厂 + */ + private static final ThreadFactory THREAD_FACTORY = r -> { + Thread thread = new Thread(r); + thread.setName("JNotepad-ThreadPool-Thread-" + THREAD_COUNT.getAndIncrement()); + thread.setDaemon(true); + // 设置异常处理器 + thread.setUncaughtExceptionHandler((t, e) -> logger.error("线程执行异常!", e)); + return thread; + }; + /** + * 拒绝处理任务时的策略 + */ + private static final RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.AbortPolicy(); + /** + * 线程池 + */ + private static final ThreadPoolExecutor THREAD_POOL = new ThreadPoolExecutor( + CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, TIME_UNIT, BLOCKING_QUEUE, THREAD_FACTORY, HANDLER); + + public static ExecutorService getThreadPool() { + return THREAD_POOL; + } +} diff --git a/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java b/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java index 6bd13af5d55c988f69a8f8177f4f43a024e4196a..00597b7f322bf61a9f5f1753241953574cf90b1a 100644 --- a/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java +++ b/src/main/java/org/jcnc/jnotepad/ui/menu/JNotepadMenuBar.java @@ -256,13 +256,13 @@ public class JNotepadMenuBar extends MenuBar { // 设置窗口为置顶 primaryStage.setAlwaysOnTop(after); }); - englishItem.setOnAction(new OpenHandler() { + englishItem.setOnAction(new LocalizationHandler() { @Override public void handle(ActionEvent actionEvent) { setCurrentLanguage(ENGLISH); } }); - chineseItem.setOnAction(new OpenHandler() { + chineseItem.setOnAction(new LocalizationHandler() { @Override public void handle(ActionEvent actionEvent) { setCurrentLanguage(CHINESE);