com.neko233.toolchain.common.base.Memoizer Maven / Gradle / Ivy
package com.neko233.toolchain.common.base;
import com.neko233.toolchain.common.annotation.ThreadSafe;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
/**
* 备忘录 with TTL. 存储相同的输入
* A memoized function stores the output corresponding to some set of specific
* inputs. Subsequent calls with remembered inputs return the remembered result
* rather than recalculating it.
*
* @author SolarisNeko
*/
@ThreadSafe
public final class Memoizer {
// 1min expire
private static final Supplier DEFAULT_EXPIRATION_NANOS = memoize(Memoizer::queryExpirationConfig,
TimeUnit.MINUTES.toNanos(1));
private Memoizer() {
}
private static long queryExpirationConfig() {
return TimeUnit.MILLISECONDS.toNanos(BaseGlobalConfig233.get(BaseGlobalConfig233.OSHI_UTIL_MEMOIZER_EXPIRATION, 300));
}
/**
* @return The number of nanoseconds to keep memoized values before refreshing
*/
public static long defaultExpiration() {
return DEFAULT_EXPIRATION_NANOS.get();
}
/**
* Store a supplier in a delegate function to be computed once, and only again
* after time to live (ttl) has expired.
*
* @param The type of object supplied
* @param original The {@link java.util.function.Supplier} to memoize
* @param ttlNanos Time in nanoseconds to retain calculation. If negative, retain
* indefinitely.
* @return A memoized version of the supplier
*/
public static Supplier memoize(Supplier original, long ttlNanos) {
// Adapted from Guava's ExpiringMemoizingSupplier
return new Supplier() {
final Supplier delegate = original;
volatile T value; // NOSONAR squid:S3077
volatile long expirationNanos;
@Override
public T get() {
long nanos = expirationNanos;
long now = System.nanoTime();
if (nanos == 0 || (ttlNanos >= 0 && now - nanos >= 0)) {
synchronized (this) {
if (nanos == expirationNanos) { // recheck for lost race
T t = delegate.get();
value = t;
nanos = now + ttlNanos;
expirationNanos = (nanos == 0) ? 1 : nanos;
return t;
}
}
}
return value;
}
};
}
/**
* Store a supplier in a delegate function to be computed only once.
*
* @param The type of object supplied
* @param original The {@link java.util.function.Supplier} to memoize
* @return A memoized version of the supplier
*/
public static Supplier memoize(Supplier original) {
return memoize(original, -1L);
}
}