From fedb4e68f75ad6864ae0059c0bf1a6caaf1d3566 Mon Sep 17 00:00:00 2001 From: Woder <17339354+wode490390@users.noreply.github.com> Date: Fri, 5 Jan 2024 21:25:37 +0800 Subject: [PATCH] virtual thread capacity --- .github/workflows/maven.yml | 1 - pom.xml | 19 +----- .../java/cn/nukkit/scheduler/AsyncTask.java | 4 ++ .../cn/nukkit/scheduler/FileWriteTask.java | 4 ++ .../cn/nukkit/scheduler/NukkitRunnable.java | 20 +++++- .../cn/nukkit/scheduler/ServerScheduler.java | 66 +++++++++++++++---- .../java/cn/nukkit/scheduler/TaskHandler.java | 8 ++- 7 files changed, 90 insertions(+), 32 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index d2f264d2a3f..5eb1804a18e 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -11,7 +11,6 @@ jobs: matrix: java: [ - 17, 21, ] steps: diff --git a/pom.xml b/pom.xml index 5e4027cfccd..69aa24355ae 100644 --- a/pom.xml +++ b/pom.xml @@ -8,8 +8,8 @@ 1.0-SNAPSHOT - 17 - 17 + 21 + 21 UTF-8 5.10.1 2.22.0 @@ -432,19 +432,4 @@ - - - - java21 - - - 21 - - - - 21 - 21 - - - diff --git a/src/main/java/cn/nukkit/scheduler/AsyncTask.java b/src/main/java/cn/nukkit/scheduler/AsyncTask.java index 3a99b0e03e8..26411fea50d 100644 --- a/src/main/java/cn/nukkit/scheduler/AsyncTask.java +++ b/src/main/java/cn/nukkit/scheduler/AsyncTask.java @@ -50,6 +50,10 @@ public int getTaskId() { return this.taskId; } + protected boolean isVirtual() { + return false; + } + public abstract void onRun(); public void onCompletion(Server server) { diff --git a/src/main/java/cn/nukkit/scheduler/FileWriteTask.java b/src/main/java/cn/nukkit/scheduler/FileWriteTask.java index 40b97301382..902caacd89c 100644 --- a/src/main/java/cn/nukkit/scheduler/FileWriteTask.java +++ b/src/main/java/cn/nukkit/scheduler/FileWriteTask.java @@ -54,4 +54,8 @@ public void onRun() { } } + @Override + protected boolean isVirtual() { + return true; + } } diff --git a/src/main/java/cn/nukkit/scheduler/NukkitRunnable.java b/src/main/java/cn/nukkit/scheduler/NukkitRunnable.java index 7139dad9972..ba220153f2d 100644 --- a/src/main/java/cn/nukkit/scheduler/NukkitRunnable.java +++ b/src/main/java/cn/nukkit/scheduler/NukkitRunnable.java @@ -30,6 +30,12 @@ public synchronized Runnable runTaskAsynchronously(Plugin plugin) throws Illegal return taskHandler.getTask(); } + public synchronized Runnable runTaskAsynchronously(Plugin plugin, boolean virtual) throws IllegalArgumentException, IllegalStateException { + checkState(); + this.taskHandler = Server.getInstance().getScheduler().scheduleTask(plugin, this, true, virtual); + return taskHandler.getTask(); + } + public synchronized Runnable runTaskLater(Plugin plugin, int delay) throws IllegalArgumentException, IllegalStateException { checkState(); this.taskHandler = Server.getInstance().getScheduler().scheduleDelayedTask(plugin, this, delay); @@ -42,6 +48,12 @@ public synchronized Runnable runTaskLaterAsynchronously(Plugin plugin, int delay return taskHandler.getTask(); } + public synchronized Runnable runTaskLaterAsynchronously(Plugin plugin, int delay, boolean virtual) throws IllegalArgumentException, IllegalStateException { + checkState(); + this.taskHandler = Server.getInstance().getScheduler().scheduleDelayedTask(plugin, this, delay, true, virtual); + return taskHandler.getTask(); + } + public synchronized Runnable runTaskTimer(Plugin plugin, int delay, int period) throws IllegalArgumentException, IllegalStateException { checkState(); this.taskHandler = Server.getInstance().getScheduler().scheduleDelayedRepeatingTask(plugin, this, delay, period); @@ -54,6 +66,12 @@ public synchronized Runnable runTaskTimerAsynchronously(Plugin plugin, int delay return taskHandler.getTask(); } + public synchronized Runnable runTaskTimerAsynchronously(Plugin plugin, int delay, int period, boolean virtual) throws IllegalArgumentException, IllegalStateException { + checkState(); + this.taskHandler = Server.getInstance().getScheduler().scheduleDelayedRepeatingTask(plugin, this, delay, period, true, virtual); + return taskHandler.getTask(); + } + /** * Gets the task id for this runnable. * @@ -72,4 +90,4 @@ private void checkState() { throw new IllegalStateException("Already scheduled as " + taskHandler.getTaskId()); } } -} \ No newline at end of file +} diff --git a/src/main/java/cn/nukkit/scheduler/ServerScheduler.java b/src/main/java/cn/nukkit/scheduler/ServerScheduler.java index 64e42eed987..e3363b34617 100644 --- a/src/main/java/cn/nukkit/scheduler/ServerScheduler.java +++ b/src/main/java/cn/nukkit/scheduler/ServerScheduler.java @@ -1,6 +1,5 @@ package cn.nukkit.scheduler; -import cn.nukkit.Server; import cn.nukkit.plugin.Plugin; import cn.nukkit.utils.PluginException; import com.google.common.util.concurrent.ThreadFactoryBuilder; @@ -85,16 +84,20 @@ public TaskHandler scheduleTask(Plugin plugin, Runnable task, boolean asynchrono return addTask(plugin, task, 0, 0, asynchronous); } + public TaskHandler scheduleTask(Plugin plugin, Runnable task, boolean asynchronous, boolean virtual) { + return addTask(plugin, task, 0, 0, asynchronous, virtual); + } + /** * @deprecated Use {@link #scheduleAsyncTask(Plugin, AsyncTask) */ @Deprecated public TaskHandler scheduleAsyncTask(AsyncTask task) { - return addTask(null, task, 0, 0, true); + return addTask(null, task, 0, 0, true, task.isVirtual()); } public TaskHandler scheduleAsyncTask(Plugin plugin, AsyncTask task) { - return addTask(plugin, task, 0, 0, true); + return addTask(plugin, task, 0, 0, true, task.isVirtual()); } public TaskHandler scheduleDelayedTask(Task task, int delay) { @@ -105,6 +108,10 @@ public TaskHandler scheduleDelayedTask(Task task, int delay, boolean asynchronou return this.addTask(task, delay, 0, asynchronous); } + public TaskHandler scheduleDelayedTask(Task task, int delay, boolean asynchronous, boolean virtual) { + return this.addTask(task, delay, 0, asynchronous, virtual); + } + /** * @deprecated Use {@link #scheduleDelayedTask(Plugin, Runnable, int) */ @@ -129,6 +136,10 @@ public TaskHandler scheduleDelayedTask(Plugin plugin, Runnable task, int delay, return addTask(plugin, task, delay, 0, asynchronous); } + public TaskHandler scheduleDelayedTask(Plugin plugin, Runnable task, int delay, boolean asynchronous, boolean virtual) { + return addTask(plugin, task, delay, 0, asynchronous, virtual); + } + /** * @deprecated Use {@link #scheduleRepeatingTask(Plugin, Runnable, int) */ @@ -153,6 +164,10 @@ public TaskHandler scheduleRepeatingTask(Plugin plugin, Runnable task, int perio return addTask(plugin, task, 0, period, asynchronous); } + public TaskHandler scheduleRepeatingTask(Plugin plugin, Runnable task, int period, boolean asynchronous, boolean virtual) { + return addTask(plugin, task, 0, period, asynchronous, virtual); + } + public TaskHandler scheduleRepeatingTask(Task task, int period) { return addTask(task, 0, period, false); } @@ -161,6 +176,10 @@ public TaskHandler scheduleRepeatingTask(Task task, int period, boolean asynchro return addTask(task, 0, period, asynchronous); } + public TaskHandler scheduleRepeatingTask(Task task, int period, boolean asynchronous, boolean virtual) { + return addTask(task, 0, period, asynchronous, virtual); + } + public TaskHandler scheduleDelayedRepeatingTask(Task task, int delay, int period) { return addTask(task, delay, period, false); } @@ -169,6 +188,10 @@ public TaskHandler scheduleDelayedRepeatingTask(Task task, int delay, int period return addTask(task, delay, period, asynchronous); } + public TaskHandler scheduleDelayedRepeatingTask(Task task, int delay, int period, boolean asynchronous, boolean virtual) { + return addTask(task, delay, period, asynchronous, virtual); + } + /** * @deprecated Use {@link #scheduleDelayedRepeatingTask(Plugin, Runnable, int, int) */ @@ -193,6 +216,10 @@ public TaskHandler scheduleDelayedRepeatingTask(Plugin plugin, Runnable task, in return addTask(plugin, task, delay, period, asynchronous); } + public TaskHandler scheduleDelayedRepeatingTask(Plugin plugin, Runnable task, int delay, int period, boolean asynchronous, boolean virtual) { + return addTask(plugin, task, delay, period, asynchronous, virtual); + } + public void cancelTask(int taskId) { TaskHandler taskHandler = taskMap.remove(taskId); if (taskHandler != null) { @@ -240,10 +267,18 @@ public boolean isQueued(int taskId) { } private TaskHandler addTask(Task task, int delay, int period, boolean asynchronous) { - return addTask(task instanceof PluginTask ? ((PluginTask) task).getOwner() : null, task, delay, period, asynchronous); + return addTask(task instanceof PluginTask ? ((PluginTask) task).getOwner() : null, task, delay, period, asynchronous, false); + } + + private TaskHandler addTask(Task task, int delay, int period, boolean asynchronous, boolean virtual) { + return addTask(task instanceof PluginTask ? ((PluginTask) task).getOwner() : null, task, delay, period, asynchronous, virtual); } private TaskHandler addTask(Plugin plugin, Runnable task, int delay, int period, boolean asynchronous) { + return addTask(plugin, task, delay, period, asynchronous, false); + } + + private TaskHandler addTask(Plugin plugin, Runnable task, int delay, int period, boolean asynchronous, boolean virtual) { if (plugin != null && plugin.isDisabled()) { throw new PluginException("Plugin '" + plugin.getName() + "' attempted to register a task while disabled."); } @@ -251,7 +286,7 @@ private TaskHandler addTask(Plugin plugin, Runnable task, int delay, int period, throw new PluginException("Attempted to register a task with negative delay or period."); } - TaskHandler taskHandler = new TaskHandler(plugin, task, nextTaskId(), asynchronous); + TaskHandler taskHandler = new TaskHandler(plugin, task, nextTaskId(), asynchronous, virtual); taskHandler.setDelay(delay); taskHandler.setPeriod(period); taskHandler.setNextRunTick(taskHandler.isDelayed() ? currentTick + taskHandler.getDelay() : currentTick); @@ -280,13 +315,20 @@ public void mainThreadHeartbeat(int currentTick) { taskMap.remove(taskHandler.getTaskId()); continue; } else if (taskHandler.isAsynchronous()) { - asyncPool.execute(() -> { - try { - taskHandler.getTask().run(); - } catch (Throwable e) { - log.fatal("Exception in asynchronous task", e); - } - }); + if (taskHandler.isVirtual()) { + Thread.ofVirtual() + .name("Nukkit Asynchronous (Virtual) Task Handler #", 0) + .uncaughtExceptionHandler((thread, ex) -> log.fatal("Exception in asynchronous (virtual) task", ex)) + .start(taskHandler.getTask()); + } else { + asyncPool.execute(() -> { + try { + taskHandler.getTask().run(); + } catch (Throwable e) { + log.fatal("Exception in asynchronous task", e); + } + }); + } } else { try { taskHandler.run(currentTick); diff --git a/src/main/java/cn/nukkit/scheduler/TaskHandler.java b/src/main/java/cn/nukkit/scheduler/TaskHandler.java index d3a7389fe82..dc6fff9dad3 100644 --- a/src/main/java/cn/nukkit/scheduler/TaskHandler.java +++ b/src/main/java/cn/nukkit/scheduler/TaskHandler.java @@ -10,6 +10,7 @@ public class TaskHandler { private final int taskId; private final boolean asynchronous; + private final boolean virtual; private final Plugin plugin; private final Runnable task; @@ -22,11 +23,12 @@ public class TaskHandler { private boolean cancelled; - public TaskHandler(Plugin plugin, Runnable task, int taskId, boolean asynchronous) { + public TaskHandler(Plugin plugin, Runnable task, int taskId, boolean asynchronous, boolean virtual) { this.asynchronous = asynchronous; this.plugin = plugin; this.task = task; this.taskId = taskId; + this.virtual = virtual; } public boolean isCancelled() { @@ -107,6 +109,10 @@ public boolean isAsynchronous() { return asynchronous; } + public boolean isVirtual() { + return virtual; + } + public void setDelay(int delay) { this.delay = delay; }