package org.handwerkszeug.common.util; import java.lang.ref.WeakReference; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.concurrent.atomic.AtomicReference; public class LazyLoadingReference<T> { protected Factory<T> factory; protected AtomicReference<WeakReference<Future<T>>> reference = new AtomicReference<WeakReference<Future<T>>>(); public LazyLoadingReference(Factory<T> factory) { this.factory = factory; } public T get() throws IllegalStateException { while (true) { WeakReference<Future<T>> ref = reference.get(); boolean valid = true; if (ref == null) { Callable<T> c = new Callable<T>() { public T call() throws Exception { return factory.create(); } }; FutureTask<T> f = new FutureTask<T>(c); ref = new WeakReference<Future<T>>(f); if (valid = reference.compareAndSet(null, ref)) { f.run(); } } if (valid) { try { Future<T> f = ref.get(); if (f != null) { return f.get(); } else { reference.compareAndSet(ref, null); } } catch (CancellationException e) { reference.compareAndSet(ref, null); } catch (Exception e) { throw new IllegalStateException(e); } } } } public interface Factory<T> { T create() throws CancellationException; } }