寻求对异步重建资源的建议/批评

时间:2011-10-18 21:33:35

标签: java asynchronous atomic nonblocking synchronized

这是建议的解决方案(我确实搜索了相同的 - 失败了)

    public abstract class AsyncCache<T> {

        /**
         * an atomic int is used here only because stamped reference doesn't take a long,
         * if it did the current thread could be used for the stamp.
         */
        private AtomicInteger threadStamp = new AtomicInteger(1);
        private AtomicStampedReference<T> reference = new AtomicStampedReference<T>(null, 0);

        protected abstract T rebuild();

        public void reset() {
            reference.set(null, 0);
        }

        public T get() {
            T obj = reference.getReference();
            if (obj != null) return obj;

            int threadID = threadStamp.incrementAndGet();

            reference.compareAndSet(null, null, 0, threadID);

            obj = rebuild();

            reference.compareAndSet(null, obj, threadID, threadID);

            return obj;

        }

    }

该过程应该很容易看到 - 资源仅在请求时构建,并通过调用reset来使其无效。

请求资源的第一个线程将其ID插入到标记的引用中,然后在生成后插入其资源版本,除非调用另一个重置。 在后续重置的情况下,第一个请求线程将返回资源的陈旧版本(是有效用例),并且在最新重置之后开始的一些请求将使用其结果填充该引用。

如果我错过了某些内容或者有更好的(更快的+更聪明的,优雅的)解决方案,请告诉我。 有一件事 - 没有故意处理MAX_INT - 不相信编程会活得足够长,但肯定很容易做到。

谢谢。

1 个答案:

答案 0 :(得分:1)

这绝对不是异步,因为请求线程将阻塞,直到rebuild()方法完成。另一个问题 - 您不检查compareAndSet返回的值。我相信你需要这样的东西

if(reference.compareAndSet(null, null, 0, threadID)) { //if resource was already reseted - rebuild
   reference.compareAndSet(null, obj, threadID, threadID);
   obj = rebuild();
} 

但是这种方法有另一个缺点 - 你必须多次重建条目(考虑到几个线程一次想要这个条目)。您可以使用该案例的未来任务(http://www.codercorp.com/blog/java/simple-concurrent-in-memory-cache-for-web-application-using-future.html)或使用{{3 }}