guava collection/cache初探
写了上面一篇,看了点eventbus相关的guava代码后,发现里面用到了很多其他guava包里的方法,所以顺着看一下,比如之前用到的map都是guava自己的
Multimap:可以包含有几个重复Key的value,你可以put进入多个不同value但是相同的key,但是又不是让后面覆盖前面的内容。
Table:二维矩阵类似,有需要这类结构可以参考
Hash:还有一堆已经实现好了的哈希方法,如果有需要可以直接用
有些代码也可以从中参考
对于Cache首先写一个例子,一般缓存肯定要考虑的是怎么存,存多久,怎么过期,初始大小,最大大小等等
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.expireAfterWrite(1000, TimeUnit.MILLISECONDS)
.expireAfterAccess(1000, TimeUnit.MILLISECONDS)
.concurrencyLevel(8)
.initialCapacity(100)
.maximumSize(100)
.weakKeys()
.weakValues()
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
return "test";
}
});
其中参数大部分一看名字就知道,这里我觉得比较特殊的是这个,看注释就明白了
@GwtIncompatible // java.lang.ref.WeakReference
public CacheBuilder<K, V> weakKeys() {
return setKeyStrength(Strength.WEAK);
}
WEAK {
@Override
<K, V> ValueReference<K, V> referenceValue(
Segment<K, V> segment, ReferenceEntry<K, V> entry, V value, int weight) {
return (weight == 1)
? new WeakValueReference<K, V>(segment.valueReferenceQueue, value, entry)
: new WeightedWeakValueReference<K, V>(
segment.valueReferenceQueue, value, entry, weight);
} @Override
Equivalence<Object> 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<ReferenceEntry<K, V>> table = this.table;
int index = hash & (table.length() - 1);
ReferenceEntry<K, V> first = table.get(index); // Look for an existing entry.
for (ReferenceEntry<K, V> 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<K, V> 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<K, V> 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<K, V> 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.
*
* <p>Note: locked reads should use {@link #recordLockedRead}.
*/
void recordRead(ReferenceEntry<K, V> entry, long now) {
if (map.recordsAccess()) {
entry.setAccessTime(now);
}
recencyQueue.add(entry);
}
guava collection/cache初探的更多相关文章
- guava学习--cache
转载:http://outofmemory.cn/java/guava/cache/how-to-use-guava-cache http://www.cnblogs.com/parryyang/ ...
- Google Guava之--cache
一.简介 Google Guava包含了Google的Java项目许多依赖的库,如:集合 [collections] .缓存 [caching] .原生类型支持 [primitives support ...
- 集合框架学习之Guava Collection
开源工具包: Guava : Google Collection Apache:Commons Collecton 1.1 Google Collections Guava:google的工程师利用传 ...
- Zookeeper + Guava loading cache 实现分布式缓存
1. 概述 项目中,创建的活动内容存入redis,然后需要用到活动内容的地方,从redis去取,然后参与计算. 活动数据的一个特点是更新不频繁.数据量不大.因为项目部署一般是多机器.多实例,除了red ...
- Google Guava -缓存cache简单使用
package guavacache; import java.util.concurrent.ExecutionException; import java.util.concurrent.Time ...
- guava之cache
转自:http://ifeve.com/google-guava-cachesexplained/ 范例 01 LoadingCache<Key, Graph> graphs = Cach ...
- HTML5 Application cache初探和企业应用启示
Application Cache 在自己做的开源项目( https://github.com/etoah/Lucien ) 用到了HTML5 的Application Cache,现总结如下: 目录 ...
- guava cache与spring集成
缓存的背景 缓存,在我们日常开发中是必不可少的一种解决性能问题的方法.简单的说,cache 就是为了提升系统性能而开辟的一块内存空间.在cpu进行计算的时候, 首先是读取寄存器,然后内存,再是硬盘.由 ...
- Guava学习笔记:Guava cache
缓存,在我们日常开发中是必不可少的一种解决性能问题的方法.简单的说,cache 就是为了提升系统性能而开辟的一块内存空间. 缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用 ...
随机推荐
- ipv6下jdbc的连接数据库方式
ipv6下jdbc的连接数据库方式 MySQL: ipv4 Driver URL: jdbc:mysql://127.0.0.1:3306/database ipv6 Driv ...
- 廖雪峰Java6IO编程-1IO基础-1IO简介
1.IO简介 IO是指Input/Output,即输入和输出: Input指从外部读取数据到内存,例如从磁盘读取,从网络读取. * 为什么要把数据读到内存才能处理这些数据呢? * 因为代码是在内存中运 ...
- docker安装testlink
testlink 镜像 https://hub.docker.com/r/bitnami/testlink ```#shell 下载镜像 docker pull bitnami/testlink
- USB-IF协会公布最新PD3.0(PPS)协议认证芯片和产品名单
原文: http://www.chongdiantou.com/wp/archives/25510.html 2017年的骁龙技术峰会高通带来了第一款兼容USB PD3.0(PPS)的QC4+充电器, ...
- [UE4]AWP狙击枪开镜
一.使用一张PNG图片,中间是透明的,其他部分是纯黑色.创建一个UserWidget.作为AWP的开镜后的准心.AWP默认状态下是没有准心的. 二.右键开镜.把第一步创建的UserWidget创建出来 ...
- 升级安装APK兼容Android7.0,解决FileUriExposedException
见http://blog.csdn.net/ruancoder/article/details/67639621?utm_source=itdadao&utm_medium=referral
- [UE4]C++代码实现播放粒子特效
转自:http://aigo.iteye.com/blog/2273345 函数参数说明(在GameplayStatics.h中) 将一个粒子放到指定位置上播放: 另一种重载形式: 将一个粒子atta ...
- sas 命令行打开SAS IDE 的代码
"C:\Program Files\SASHome\SASFoundation\9.4\sas.exe" -CONFIG "C:\Program Files\SASHom ...
- TP5实现邮件发送(PHP 利用QQ邮箱发送邮件「PHPMailer」)
在 PHP 应用开发中,往往需要验证用户邮箱.发送消息通知,而使用 PHP 内置的 mail() 函数,则需要邮件系统的支持. 如果熟悉 IMAP/SMTP 协议,结合 Socket 功能就可以编写邮 ...
- 免安装版本Mysql配置
免安装版本mysql配置如下:(本人使用的是5.6.42) 1. 解压后将/bin目录配置在系统变量中 2. 在mysql目录下新建my.ini文件配置如下信息: [mysqld] basedir=D ...