All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hutool.core.lang.SimpleCache Maven / Gradle / Ivy

There is a newer version: 5.8.33
Show newest version
package cn.hutool.core.lang;

import cn.hutool.core.collection.TransIter;
import cn.hutool.core.lang.func.Func0;
import cn.hutool.core.lang.mutable.Mutable;
import cn.hutool.core.lang.mutable.MutableObj;
import cn.hutool.core.map.WeakConcurrentMap;

import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Predicate;

/**
 * 简单缓存,无超时实现,默认使用{@link WeakConcurrentMap}实现缓存自动清理
 *
 * @param  键类型
 * @param  值类型
 * @author Looly
 */
public class SimpleCache implements Iterable>, Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 池
	 */
	private final Map, V> rawMap;
	// 乐观读写锁
	private final ReadWriteLock lock = new ReentrantReadWriteLock();
	/**
	 * 写的时候每个key一把锁,降低锁的粒度
	 */
	protected final Map keyLockMap = new ConcurrentHashMap<>();

	/**
	 * 构造,默认使用{@link WeakHashMap}实现缓存自动清理
	 */
	public SimpleCache() {
		this(new WeakConcurrentMap<>());
	}

	/**
	 * 构造
	 * 

* 通过自定义Map初始化,可以自定义缓存实现。
* 比如使用{@link WeakHashMap}则会自动清理key,使用HashMap则不会清理
* 同时,传入的Map对象也可以自带初始化的键值对,防止在get时创建 *

* * @param initMap 初始Map,用于定义Map类型 */ public SimpleCache(Map, V> initMap) { this.rawMap = initMap; } /** * 从缓存池中查找值 * * @param key 键 * @return 值 */ public V get(K key) { lock.readLock().lock(); try { return rawMap.get(MutableObj.of(key)); } finally { lock.readLock().unlock(); } } /** * 从缓存中获得对象,当对象不在缓存中或已经过期返回Func0回调产生的对象 * * @param key 键 * @param supplier 如果不存在回调方法,用于生产值对象 * @return 值对象 */ public V get(K key, Func0 supplier) { return get(key, null, supplier); } /** * 从缓存中获得对象,当对象不在缓存中或已经过期返回Func0回调产生的对象 * * @param key 键 * @param validPredicate 检查结果对象是否可用,如是否断开连接等 * @param supplier 如果不存在回调方法或结果不可用,用于生产值对象 * @return 值对象 * @since 5.7.9 */ public V get(K key, Predicate validPredicate, Func0 supplier) { V v = get(key); if((null != validPredicate && null != v && false == validPredicate.test(v))){ v = null; } if (null == v && null != supplier) { //每个key单独获取一把锁,降低锁的粒度提高并发能力,see pr#1385@Github final Lock keyLock = keyLockMap.computeIfAbsent(key, k -> new ReentrantLock()); keyLock.lock(); try { // 双重检查,防止在竞争锁的过程中已经有其它线程写入 v = get(key); if (null == v || (null != validPredicate && false == validPredicate.test(v))) { try { v = supplier.call(); } catch (Exception e) { throw new RuntimeException(e); } put(key, v); } } finally { keyLock.unlock(); keyLockMap.remove(key); } } return v; } /** * 放入缓存 * * @param key 键 * @param value 值 * @return 值 */ public V put(K key, V value) { // 独占写锁 lock.writeLock().lock(); try { rawMap.put(MutableObj.of(key), value); } finally { lock.writeLock().unlock(); } return value; } /** * 移除缓存 * * @param key 键 * @return 移除的值 */ public V remove(K key) { // 独占写锁 lock.writeLock().lock(); try { return rawMap.remove(MutableObj.of(key)); } finally { lock.writeLock().unlock(); } } /** * 清空缓存池 */ public void clear() { // 独占写锁 lock.writeLock().lock(); try { this.rawMap.clear(); } finally { lock.writeLock().unlock(); } } @Override public Iterator> iterator() { return new TransIter<>(this.rawMap.entrySet().iterator(), (entry)-> new Map.Entry() { @Override public K getKey() { return entry.getKey().get(); } @Override public V getValue() { return entry.getValue(); } @Override public V setValue(V value) { return entry.setValue(value); } }); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy