From 2fdc9a7cc58e96a4c7e4aa640eadc316c5f8cf17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9trus=20Pradella?= Date: Fri, 9 Aug 2024 07:36:34 -0300 Subject: [PATCH] Use a separated ScheduledThreadPoolExecutor for the SmartCachedYamlFileHolder because scheduling too many things sucks --- .../caching/SmartCachedYamlFileHolder.java | 46 ++++++++++++------- .../config/yaml/helper/CfgExecutor.java | 15 +++--- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/main/java/br/com/finalcraft/evernifecore/config/yaml/caching/SmartCachedYamlFileHolder.java b/src/main/java/br/com/finalcraft/evernifecore/config/yaml/caching/SmartCachedYamlFileHolder.java index 6d7e80a0..47ff68ce 100644 --- a/src/main/java/br/com/finalcraft/evernifecore/config/yaml/caching/SmartCachedYamlFileHolder.java +++ b/src/main/java/br/com/finalcraft/evernifecore/config/yaml/caching/SmartCachedYamlFileHolder.java @@ -1,17 +1,17 @@ package br.com.finalcraft.evernifecore.config.yaml.caching; +import br.com.finalcraft.evernifecore.config.yaml.helper.CfgExecutor; import br.com.finalcraft.evernifecore.config.yaml.helper.ConfigHelper; -import br.com.finalcraft.evernifecore.scheduler.FCScheduler; import org.simpleyaml.configuration.file.YamlFile; import java.io.File; import java.io.IOException; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; public class SmartCachedYamlFileHolder implements IHasYamlFile { - private static final long SECONDS_OF_CACHE = TimeUnit.MINUTES.toSeconds(5); + private static final long MINUTES_OF_CACHE = 5; private YamlFile yamlFile; private long lastUsed = 0; @@ -21,12 +21,12 @@ public class SmartCachedYamlFileHolder implements IHasYamlFile { private String contentAsString; private boolean hasComments; - private final ReentrantLock lock = new ReentrantLock(); + private transient ScheduledFuture scheduledFuture; public SmartCachedYamlFileHolder(YamlFile yamlFile) { this.yamlFile = yamlFile; this.hasComments = yamlFile.options().useComments(); - scheduleExpirationRunnable(TimeUnit.MINUTES.toSeconds(3));//Do a Faster first lookup + scheduleExpirationRunnable((int) Math.ceil(MINUTES_OF_CACHE / 2d), TimeUnit.MINUTES); //Do a Faster first lookup } @Override @@ -42,7 +42,7 @@ public synchronized YamlFile getYamlFile() { } catch (IOException e) { throw new RuntimeException("Failed to Re-Read a SmartCached YamlFile, this should never happen!!!! ?!?!?!", e); } - scheduleExpirationRunnable(SECONDS_OF_CACHE); + scheduleExpirationRunnable(MINUTES_OF_CACHE, TimeUnit.MINUTES); } return yamlFile; } @@ -61,20 +61,32 @@ public synchronized void cacheToString(){ this.yamlFile = null;//free for GC to collect } - public void scheduleExpirationRunnable(long secondsToWait){ - FCScheduler.getScheduler().schedule(() -> { - if (this.innerGetYamlFile() == null){ - return;//It means was cached to string manually + public void scheduleExpirationRunnable(long delay, TimeUnit timeUnit){ + if (scheduledFuture != null && !scheduledFuture.isCancelled() && !scheduledFuture.isDone()){ + scheduledFuture.cancel(false); + scheduledFuture = null; + } + + if (delay < 0){ + if (this.innerGetYamlFile() != null) { + cacheToString(); } + return; + } - boolean usedAtLeastOnceOnTheLastThreeMinutes = System.currentTimeMillis() < getLastUsed() + TimeUnit.SECONDS.toMillis(SECONDS_OF_CACHE); + this.scheduledFuture = CfgExecutor.getScheduler().schedule(() -> { + if (this.innerGetYamlFile() != null) { + + boolean usedAtLeastOnceOnTheLastThreeMinutes = System.currentTimeMillis() < getLastUsed() + TimeUnit.MINUTES.toMillis(MINUTES_OF_CACHE); + + if (usedAtLeastOnceOnTheLastThreeMinutes) { + //Lets do nothing, just check again in MINUTES_OF_CACHE minutes + scheduleExpirationRunnable(MINUTES_OF_CACHE, TimeUnit.MINUTES); + } else { + cacheToString(); + } - if (usedAtLeastOnceOnTheLastThreeMinutes) { - //Lets do nothing, just check again in 3 minutes - scheduleExpirationRunnable(SECONDS_OF_CACHE); - } else { - cacheToString(); } - }, secondsToWait, TimeUnit.SECONDS); + }, delay, timeUnit); } } diff --git a/src/main/java/br/com/finalcraft/evernifecore/config/yaml/helper/CfgExecutor.java b/src/main/java/br/com/finalcraft/evernifecore/config/yaml/helper/CfgExecutor.java index 4e03c520..121c4070 100644 --- a/src/main/java/br/com/finalcraft/evernifecore/config/yaml/helper/CfgExecutor.java +++ b/src/main/java/br/com/finalcraft/evernifecore/config/yaml/helper/CfgExecutor.java @@ -2,16 +2,19 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.logging.Logger; public class CfgExecutor { private static final Logger logger = Logger.getLogger("CfgExecutor"); + private static final ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(10); + + public static ScheduledThreadPoolExecutor getScheduler() { + return scheduler; + } + public static ExecutorService EXECUTOR_SERVICE; static { createExecutorService(); @@ -38,14 +41,14 @@ public static synchronized void shutdownExecutor(){ EXECUTOR_SERVICE.shutdown(); boolean success = EXECUTOR_SERVICE.awaitTermination(30, TimeUnit.SECONDS); if (!success){ - logger.warning("Failed to close ConfigHelper Scheduller, TimeOut of 30 seconds Reached, this is really bad! Terminating all of them now!"); + logger.warning("Failed to close ConfigHelper Scheduler, TimeOut of 30 seconds Reached, this is really bad! Terminating all of them now!"); EXECUTOR_SERVICE.shutdownNow(); } } catch (InterruptedException e){ e.printStackTrace(); } }else { - throw new IllegalStateException("Tried to stop the ConfigHelper Scheduller while it was not running at all!"); + throw new IllegalStateException("Tried to stop the ConfigHelper Scheduler while it was not running at all!"); } } }