Scheduler
Package: dev.anchorlight.stonelib.scheduler
SchedulerService wraps the Bukkit scheduler with two additions: it remembers every task it creates, so cancelAll() in onDisable stops them all, and supplyAsync runs slow work off the main thread and hands the result back on it.
API
| Method | Runs on | Meaning |
|---|---|---|
new SchedulerService(Plugin) | ||
runSync(Runnable) | main | Next tick. |
runSyncLater(Runnable, long delayTicks) | main | After a delay. |
runTimer(Runnable, long delayTicks, long periodTicks) | main | Repeating. |
runAsync(Runnable) | async | As soon as possible. |
runAsyncLater(Runnable, long delayTicks) | async | After a delay. |
runAsyncTimer(Runnable, long delayTicks, long periodTicks) | async | Repeating. |
supplyAsync(Supplier<T>, Consumer<T>) | async, then main | Computes a value off-thread, then passes it to the callback on the main thread. |
track(BukkitTask) | Adds a task created elsewhere, so cancelAll covers it. Returns the same task. | |
trackedCount() | How many tasks are tracked. | |
cancelAll() | Cancels every tracked task and forgets them. Safe to call more than once. |
Every run method returns the BukkitTask, so you can still cancel a single task yourself. There are 20 ticks in a second; Durations.toTicks converts a Duration.
Example
@Override
public void onEnable() {
scheduler = new SchedulerService(this);
scheduler.runTimer(this::tickArenas, 20L, 20L); // every second
scheduler.runAsyncTimer(repository::save, 6000L, 6000L); // autosave every five minutes
getServer().getPluginManager().registerEvents(new Listener() {
@EventHandler
public void onJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
scheduler.supplyAsync(
() -> repository.reload(player.getUniqueId()),
profile -> {
if (player.isOnline() && profile != null) {
player.setLevel(profile.level());
}
});
}
}, this);
}
@Override
public void onDisable() {
scheduler.cancelAll();
}
Check player.isOnline() in a callback, as above. The player can leave while the async part is running.
Behaviour to know about
supplyAsynchas no error path. If the supplier throws, the callback never runs, and Paper logs the exception as a failed task. Catch exceptions inside the supplier and return something the callback can act on, such asnullor anOptional.- Tasks are only forgotten by
cancelAll. A one-shot task that has finished, or a task you cancelled yourself, stays in the tracked set until then. That is harmless, but it meanstrackedCountcounts every task created since the lastcancelAll, not only the live ones. - A plugin's tasks are cancelled on disable anyway. Paper cancels them when a plugin disables.
cancelAllstill matters for reload commands that restart timers, and for stopping repeating tasks before you flush data inonDisable, so a timer cannot fire half-way through shutdown. - No Folia support. This wraps the classic Bukkit scheduler, which Folia does not provide.