I have encountered this situation several times. What you need is a singleton LockFactory, which is actually a weak link dictionary for lock objects. the code should look something like this:
class LockFactory { private LockFactory() {} private LockFactory instance = null; public static LockFactory getInstance() { if (this.instance == null) this.instance = new LockFactory(); return this.instance; } private int _last_check_size = 0; private int _cleanup_size = 1000; private Map<String, WeakReference> weakRefDictionary = new HashMap<String, WeakReference>(); public object getLock(String id) { synchronized(this) { if (!this.weakRefDictionary.containsKey(id)) this.weakRefDictionary.put(id, new WeakReference(null)); Object lock = this.weakRefDictionary.get(id).Target; if (lock == null) { lock = new Object(); this.weakRefDictionary.get(id).Target = lock; } if (this.weakRefDictionary.size() > this._last_check_size + this._cleanup_size) this._do_cleanup(); return lock; } } public void _do_cleanup() { synchronized(this) { Iterator<Map.Entry<String, WeakReference>> iter = this.weakRefDictionary.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<String,WeakReference> entry = iter.next(); if (entry.getValue().get() == null) { iter.remove(); } } this._last_check_size = this.weakRefDictionary.size(); } } }
Now for use in your case, simply do:
public void beforeUpdated(Log log){ synchronized(LockFactory.getInstance().getLock(log.getUuid())){ query(log); merge(log); persist(log); } }
source share