博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
guava collection/cache初探
阅读量:5346 次
发布时间:2019-06-15

本文共 5932 字,大约阅读时间需要 19 分钟。

写了上面一篇,看了点eventbus相关的guava代码后,发现里面用到了很多其他guava包里的方法,所以顺着看一下,比如之前用到的map都是guava自己的

Multimap:可以包含有几个重复Key的value,你可以put进入多个不同value但是相同的key,但是又不是让后面覆盖前面的内容。

Table:二维矩阵类似,有需要这类结构可以参考

Hash:还有一堆已经实现好了的哈希方法,如果有需要可以直接用

有些代码也可以从中参考

对于Cache首先写一个例子,一般缓存肯定要考虑的是怎么存,存多久,怎么过期,初始大小,最大大小等等

LoadingCache
cache = CacheBuilder.newBuilder() .expireAfterWrite(1000, TimeUnit.MILLISECONDS) .expireAfterAccess(1000, TimeUnit.MILLISECONDS) .concurrencyLevel(8) .initialCapacity(100) .maximumSize(100) .weakKeys() .weakValues() .build(new CacheLoader
() { @Override public String load(String key) throws Exception { return "test"; } });

其中参数大部分一看名字就知道,这里我觉得比较特殊的是这个,看注释就明白了

@GwtIncompatible // java.lang.ref.WeakReference  public CacheBuilder
weakKeys() { return setKeyStrength(Strength.WEAK); }
WEAK {      @Override      
ValueReference
referenceValue( Segment
segment, ReferenceEntry
entry, V value, int weight) { return (weight == 1) ? new WeakValueReference
(segment.valueReferenceQueue, value, entry) : new WeightedWeakValueReference
( segment.valueReferenceQueue, value, entry, weight); } @Override Equivalence
defaultEquivalence() { return Equivalence.identity(); } };

 

put放入元素,跟一般的没多大区别,就是计算下hash,找到对应的index放进去,就是map的一般原理

@Override  public V put(K key, V value) {    checkNotNull(key);    checkNotNull(value);    int hash = hash(key);    return segmentFor(hash).put(key, hash, value, false);  }

来看具体的put,起始也比较好懂

@Nullable    V put(K key, int hash, V value, boolean onlyIfAbsent) {      lock();      try {        long now = map.ticker.read();        preWriteCleanup(now);        int newCount = this.count + 1;        if (newCount > this.threshold) { // ensure capacity          expand();          newCount = this.count + 1;        }        AtomicReferenceArray
> table = this.table; int index = hash & (table.length() - 1); ReferenceEntry
first = table.get(index); // Look for an existing entry. for (ReferenceEntry
e = first; e != null; e = e.getNext()) { K entryKey = e.getKey(); if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { // We found an existing entry. ValueReference
valueReference = e.getValueReference(); V entryValue = valueReference.get(); if (entryValue == null) { ++modCount; if (valueReference.isActive()) { enqueueNotification( key, hash, entryValue, valueReference.getWeight(), RemovalCause.COLLECTED); setValue(e, key, value, now); newCount = this.count; // count remains unchanged } else { setValue(e, key, value, now); newCount = this.count + 1; } this.count = newCount; // write-volatile evictEntries(e); return null; } else if (onlyIfAbsent) { // Mimic // "if (!map.containsKey(key)) ... // else return map.get(key); recordLockedRead(e, now); return entryValue; } else { // clobber existing entry, count remains unchanged ++modCount; enqueueNotification( key, hash, entryValue, valueReference.getWeight(), RemovalCause.REPLACED); setValue(e, key, value, now); evictEntries(e); return entryValue; } } } // Create a new entry. ++modCount; ReferenceEntry
newEntry = newEntry(key, hash, first); setValue(newEntry, key, value, now); table.set(index, newEntry); newCount = this.count + 1; this.count = newCount; // write-volatile evictEntries(newEntry); return null; } finally { unlock(); postWriteCleanup(); } }
void runLockedCleanup(long now) {      if (tryLock()) {        try {          drainReferenceQueues();          expireEntries(now); // calls drainRecencyQueue          readCount.set(0);        } finally {          unlock();        }      }    }

再看下get

@Override  public @Nullable V get(@Nullable Object key) {    if (key == null) {      return null;    }    int hash = hash(key);    return segmentFor(hash).get(key, hash);  }
@Nullable    V get(Object key, int hash) {      try {        if (count != 0) { // read-volatile          long now = map.ticker.read();          ReferenceEntry
e = getLiveEntry(key, hash, now); if (e == null) { return null; } V value = e.getValueReference().get(); if (value != null) { recordRead(e, now); return scheduleRefresh(e, e.getKey(), hash, value, now, map.defaultLoader); } tryDrainReferenceQueues(); } return null; } finally { postReadCleanup(); } }
/**     * Records the relative order in which this read was performed by adding {
@code entry} to the * recency queue. At write-time, or when the queue is full past the threshold, the queue will be * drained and the entries therein processed. * *

Note: locked reads should use {

@link #recordLockedRead}. */ void recordRead(ReferenceEntry
entry, long now) { if (map.recordsAccess()) { entry.setAccessTime(now); } recencyQueue.add(entry); }

 

转载于:https://www.cnblogs.com/it-worker365/p/9946588.html

你可能感兴趣的文章
Java中的编码
查看>>
PKUWC2018 5/6
查看>>
As-If-Serial 理解
查看>>
洛谷P1005 矩阵取数游戏
查看>>
在Silverlight中使用HierarchicalDataTemplate为TreeView实现递归树状结构
查看>>
无线通信基础(一):无线网络演进
查看>>
如何在工作中快速成长?阿里资深架构师给工程师的10个简单技巧
查看>>
WebSocket 时时双向数据,前后端(聊天室)
查看>>
关于python中带下划线的变量和函数 的意义
查看>>
linux清空日志文件内容 (转)
查看>>
安卓第十三天笔记-服务(Service)
查看>>
Servlet接收JSP参数乱码问题解决办法
查看>>
Ajax : load()
查看>>
MySQL-EXPLAIN执行计划Extra解释
查看>>
Zookeeper概述
查看>>
Zookeeper一致性级别
查看>>
Linux远程登录
查看>>
Linux自己安装redis扩展
查看>>
HDU 1016 Prime Ring Problem(dfs)
查看>>
C#中结构体与字节流互相转换
查看>>