# caffeine-demo
**Repository Path**: linkrwx/caffeine-demo
## Basic Information
- **Project Name**: caffeine-demo
- **Description**: No description available
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 2
- **Created**: 2021-06-17
- **Last Updated**: 2021-06-17
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
@[toc]
## Java高性能本地缓存框架Caffeine
> 缓存又分进程内缓存和分布式缓存两种:分布式缓存如redis、memcached等,还有本地(进程内)缓存如ehcache、GuavaCache、Caffeine等
> Caffeine是一个基于Java8开发的提供了[近乎最佳](https://github.com/ben-manes/caffeine/wiki/Efficiency-zh-CN)命中率的[高性能](https://github.com/ben-manes/caffeine/wiki/Benchmarks-zh-CN)的缓存库。
> Caffeine 是一个基于Java 8的高性能本地缓存框架,其结构和 Guava Cache 基本一样,api也一样,基本上很容易就能替换。 Caffeine 实际上就是在 Guava Cache 的基础上,利用了一些 Java 8 的新特性,提高了某些场景下的性能效率。
文档参考:https://github.com/ben-manes/caffeine/wiki/Home-zh-CN
### 如何使用
在项目中添加Caffeine的依赖
```xml
4.0.0
org.example
caffeine-demo
1.0-SNAPSHOT
org.apache.maven.plugins
maven-compiler-plugin
8
8
com.github.ben-manes.caffeine
caffeine
2.8.6
org.junit.jupiter
junit-jupiter-engine
5.5.2
test
```
### 缓存加载
Caffeine提供了四种缓存添加策略:手动加载,自动加载,手动异步加载和自动异步加载。
#### 手动加载
Caffeine 有两种方式限制缓存大小。**两种配置互斥,不能同时配置**
1. **创建一个限制容量 Cache**
```java
Cache cache = Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.SECONDS) // 设置超时时间为5s / 写入后隔段时间过期
.maximumSize(1)// 设置缓存最大条目数,超过条目则触发回收。
.build();
```
需要注意的是,实际实现上为了性能考虑,这个限制并不会很死板:
- 在缓存元素个数快要达到最大限制的时候,过期策略就开始执行了,所以在达到最大容量前也许某些不太可能再次访问的 Entry (Key-Value)就被过期掉了。
- 有时候因为过期 Entry 任务还没执行完,更多的 Entry 被放入缓存,导致缓存的 Entry 个数短暂超过了这个限制
示例:
```java
/**
* 手动加载cache
*/
@Test
public void testManualLoadCache2() throws InterruptedException {
Cache cache = Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.SECONDS) // 设置超时时间为5s / 写入后隔段时间过期
.maximumSize(1)// 设置缓存最大条目数,超过条目则触发回收。
.build();
// 查找一个缓存元素, 没有查找到的时候返回null
String value = cache.getIfPresent("test");
System.out.println(value);//-->null
// 查找缓存,如果缓存不存在则生成缓存元素, 如果无法生成则返回null
value = cache.get("test", k -> "test-value");
System.out.println(cache.getIfPresent("test"));//-->test-value
System.out.println(value);//-->test-value
// 加入一些缓存数据
List list = new ArrayList<>();
for (int i = 2; i < 10; i++) {
list.add("test" + i);
}
for (int i = 2; i < 10; i++) {
// 添加或者更新一个缓存元素
cache.put("test" + i, "test-value" + i);
}
// 执行缓存回收
// 缓存的删除策略使用的是惰性删除和定时删除,但是我也可以自己调用cache.cleanUp()方法手动触发一次回收操作。cache.cleanUp()是一个同步方法。
cache.cleanUp();
//根据key list去获取一个map的缓存
Map dataObjectMap
= cache.getAllPresent(list);
//查看缓存中的数据
System.out.println(dataObjectMap.size()); //--> 1
System.out.println(dataObjectMap); //--> {test9=test-value9}
Thread.sleep(5000); //设置10s的睡眠时间,使得超过过期时间
System.out.println(cache.getIfPresent("test"));//-->null
}
```
2. **创建一个自定义权重限制容量的 Cache**
```java
Cache> stringListCache = Caffeine.newBuilder()
//最大weight值,当所有entry的weight和快达到这个限制的时候会发生缓存过期,剔除一些缓存
.maximumWeight(1)
//每个 Entry 的 weight 值
.weigher(new Weigher>() {
@Override
public @NonNegative int weigh(@NonNull String key, @NonNull List