I have class whose instances can create a self-wrapped copy of its own.
class Some {
static class Nullable extends Some {
Nullable(Some wrapped) { this.wrapped = wrapped; }
@Override public void doSome() {}
final Some wrapped;
}
Some nullable() {
new Nullable(this);
}
public void soSome() {}
}
Now I need to implement some caching for a Some
value and its nullable()
value.
I found I shouldn't use the WeakHashMap<Some, Some>
cuz each has a strong reference to the key(wrapped
), right?
How can I implement caching with/without changing the Some
class, without any 3rd party library?
I'm trying to do like this. Is this the way?
private static final Map<Some, Some> MAP = new HashMap<>(); // TODO: synchronize!
private static final ReferenceQueue<Some> QUEUE = new ReferenceQueue<>();
private static volatile Thread thread = null;
@SuppressWarnings({"unchecked"})
static Some get(final Some some) {
synchronized (TheClass.class) {
if (thread == null) {
thread = new Thread(() -> {
while (true) {
try {
Reference<? extends Some> reference = QUEUE.remove();
Some key = reference.get(); // can be null?
Some value = MAP.remove(key);
} catch (final InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
});
thread.setDaemon(true);
thread.start();
}
}
return (T) MAP.computeIfAbsent(some, k -> {
final boolean enqueued = new WeakReference<>(k, QUEUE).enqueue();
assert enqueued;
return k.nullable();
});
}
Follow-up question. Can the reference.get()
part really return null
?