Per-key blocking Map in Java

后端 未结 3 1408
孤城傲影
孤城傲影 2021-02-07 23:02

I\'m dealing with some third-party library code that involves creating expensive objects and caching them in a Map. The existing implementation is something like

3条回答
  •  孤独总比滥情好
    2021-02-07 23:33

    public class Cache {
    
        private static final Set lockedKeys = new HashSet<>();
    
        private void lock(String key) {
            synchronized (lockedKeys) {
                while (!lockedKeys.add(key)) {
                    try {
                        lockedKeys.wait();
                    } catch (InterruptedException e) {
                        log.error("...");
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    
        private void unlock(String key) {
            synchronized (lockedKeys) {
                lockedKeys.remove(key);
                lockedKeys.notifyAll();
            }
        }
    
        public Foo getFromCache(String key) {
            try {
                lock(key);
    
                Foo result = cache.get(key);
                if (result == null) {
                    result = createFooExpensively(key);
                    cache.put(key, result);
                }
                return result;
                //For different keys it is executed in parallel.
                //For the same key it is executed synchronously.
    
            } finally {
                unlock(key);
            }
        }
    
    }
    
    • key can be not only a 'String' but any class with correctly overridden 'equals' and 'hashCode' methods.
    • try-finally - is very important - you must guarantee to unlock waiting threads after your operation even if your operation threw exception.
    • It will not work if your back-end is distributed across multiple servers/JVMs.

提交回复
热议问题