🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
~~~ package org.apache.ibatis.cache.decorators; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.ibatis.cache.Cache; import org.apache.ibatis.cache.CacheException; /** * Simple blocking decorator * * Simple and inefficient version of EhCache's BlockingCache decorator. * It sets a lock over a cache key when the element is not found in cache. * This way, other threads will wait until this element is filled instead of hitting the database. * * @author Eduardo Macarron * */ public class BlockingCache implements Cache { //超时时间 private long timeout; //缓存实体 private final Cache delegate; //可重入锁 private final ConcurrentHashMap<Object, ReentrantLock> locks; //构造器 public BlockingCache(Cache delegate) { this.delegate = delegate; this.locks = new ConcurrentHashMap<>(); } //获取id @Override public String getId() { return delegate.getId(); } //获取长度 @Override public int getSize() { return delegate.getSize(); } //放入数据,并释放锁 @Override public void putObject(Object key, Object value) { try { delegate.putObject(key, value); } finally { releaseLock(key); } } //获取对象,并释放锁 @Override public Object getObject(Object key) { acquireLock(key); Object value = delegate.getObject(key); if (value != null) { releaseLock(key); } return value; } //删除对象,并释放锁 @Override public Object removeObject(Object key) { // despite of its name, this method is called only to release locks releaseLock(key); return null; } //清除数据 @Override public void clear() { delegate.clear(); } //根据key获取对应的锁,一个对象一个锁 private ReentrantLock getLockForKey(Object key) { return locks.computeIfAbsent(key, k -> new ReentrantLock()); } //获取对象的锁 private void acquireLock(Object key) { Lock lock = getLockForKey(key); if (timeout > 0) { try { boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS); if (!acquired) { throw new CacheException("Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + delegate.getId()); } } catch (InterruptedException e) { throw new CacheException("Got interrupted while trying to acquire lock for key " + key, e); } } else { lock.lock(); } } //释放锁 private void releaseLock(Object key) { ReentrantLock lock = locks.get(key); //判断是否被当前线程持有 if (lock.isHeldByCurrentThread()) { lock.unlock(); } } //获取超时时间-毫秒 public long getTimeout() { return timeout; } //设置超时时间-毫秒 public void setTimeout(long timeout) { this.timeout = timeout; } } ~~~