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;
}