├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── misc.xml
├── uiDesigner.xml
├── vcs.xml
└── workspace.xml
├── JavaBasicSkills.iml
├── README.md
├── pom.xml
├── src
└── main
│ ├── java
│ └── com
│ │ └── veezean
│ │ └── skills
│ │ ├── cache
│ │ ├── CacheItem.java
│ │ ├── DemoCache.java
│ │ ├── PostInfo.java
│ │ ├── PostService.java
│ │ ├── caffeine
│ │ │ ├── CaffeineCacheService.java
│ │ │ ├── Department.java
│ │ │ ├── DepartmentDao.java
│ │ │ └── UserDao.java
│ │ ├── ehcache
│ │ │ └── EhcacheService.java
│ │ ├── framework
│ │ │ ├── CacheFactory.java
│ │ │ ├── CacheItem.java
│ │ │ ├── CacheManager.java
│ │ │ ├── CacheType.java
│ │ │ ├── DefaultCache.java
│ │ │ ├── ICache.java
│ │ │ ├── ICacheHandler.java
│ │ │ ├── ICacheManager.java
│ │ │ ├── LruCache.java
│ │ │ ├── LruHashMap.java
│ │ │ ├── Main.java
│ │ │ ├── UseCache.java
│ │ │ └── User.java
│ │ ├── fwk
│ │ │ ├── Main.java
│ │ │ ├── MemCacheManager.java
│ │ │ ├── MyCache.java
│ │ │ ├── MyCachingProvider.java
│ │ │ └── MyConfiguration.java
│ │ ├── guava
│ │ │ ├── CacheConfig.java
│ │ │ ├── CacheService.java
│ │ │ ├── GuavaCacheService.java
│ │ │ ├── MyCacheLoader.java
│ │ │ ├── User.java
│ │ │ └── UserDao.java
│ │ ├── jsr
│ │ │ ├── Book.java
│ │ │ └── BookService.java
│ │ └── springcache
│ │ │ └── SpringCacheTest.java
│ │ ├── classloader
│ │ └── Main.java
│ │ ├── function
│ │ ├── Car.java
│ │ ├── FunctionCodeTest.java
│ │ ├── FunctionService.java
│ │ ├── NetworkDetail.java
│ │ ├── PersonalFunction.java
│ │ ├── PriceComputer.java
│ │ ├── PriceInfo.java
│ │ ├── Train.java
│ │ ├── Truck.java
│ │ ├── VmDetail.java
│ │ └── api
│ │ │ ├── FunctionCodeTest.java
│ │ │ ├── IResource.java
│ │ │ ├── NetworkDetail.java
│ │ │ ├── ResourcePriceManage.java
│ │ │ └── VmDetail.java
│ │ ├── future
│ │ ├── ComparePriceService.java
│ │ ├── FutureService.java
│ │ ├── HttpRequestMock.java
│ │ ├── LogHelper.java
│ │ ├── PriceResult.java
│ │ └── TestThread.java
│ │ ├── iterator
│ │ ├── Project.java
│ │ ├── Requirement.java
│ │ ├── Service.java
│ │ └── Task.java
│ │ ├── lock
│ │ ├── DeployedProcessService.java
│ │ ├── LockTest.java
│ │ ├── Main.java
│ │ ├── ThreadLocalUsage.java
│ │ ├── ThreadTest.java
│ │ ├── VmService.java
│ │ └── cas
│ │ │ ├── CasService.java
│ │ │ └── Item.java
│ │ ├── oa
│ │ ├── Attendance.java
│ │ ├── ClockInRecord.java
│ │ ├── Department.java
│ │ ├── LoginReq.java
│ │ ├── Main.java
│ │ ├── Notice.java
│ │ ├── Response.java
│ │ ├── Role.java
│ │ ├── ShortUser.java
│ │ ├── User.java
│ │ └── UserRole.java
│ │ ├── optional
│ │ ├── Attachment.java
│ │ ├── Company.java
│ │ ├── Content.java
│ │ ├── Department.java
│ │ ├── Employee.java
│ │ ├── HttpServletRequest.java
│ │ ├── OptionalService.java
│ │ ├── PostDetail.java
│ │ ├── Team.java
│ │ ├── TestException.java
│ │ └── User.java
│ │ ├── stream
│ │ ├── Dept.java
│ │ ├── StreamService.java
│ │ ├── User.java
│ │ └── collect
│ │ │ ├── CollectService.java
│ │ │ ├── Employee.java
│ │ │ ├── MyCollector.java
│ │ │ └── Score.java
│ │ ├── swagger
│ │ ├── ApiPropertyReference.java
│ │ ├── OperateLog.java
│ │ ├── OperateType.java
│ │ ├── SwaggerDisplayEnum.java
│ │ └── SwaggerEnumPropertyBuilderPlugin.java
│ │ ├── test
│ │ ├── Resource.java
│ │ ├── SensitiveResourceApplyService.java
│ │ ├── Test.java
│ │ └── User.java
│ │ ├── test333
│ │ └── Main.java
│ │ └── util
│ │ └── StringUtils.java
│ └── resources
│ └── META-INF
│ └── services
│ └── javax.cache.spi.CachingProvider
└── target
└── classes
└── META-INF
└── services
└── javax.cache.spi.CachingProvider
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | com.veezean
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | 1663466164917
195 |
196 |
197 | 1663466164917
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 | jar://$MAVEN_REPOSITORY$/com/github/ben-manes/caffeine/caffeine/2.9.3/caffeine-2.9.3-sources.jar!/com/github/benmanes/caffeine/cache/BoundedLocalCache.java
237 | 654
238 |
239 |
240 |
241 |
242 |
243 |
--------------------------------------------------------------------------------
/JavaBasicSkills.iml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JAVA深入技能细节剖析
2 |
3 | JAVA细节、JAVA使用细节剖析相关文档汇总整理,以及相关文档中涉及的演示代码统一存放。
4 |
5 |
6 | ## 📢关于我
7 |
8 | 多年软件开发与系统架构经验,擅长用最朴实的方式讲透软件开发与系统架构技术,也可以将程序员最真实的职场打怪技能、代码之外的生存软技能娓娓道来。
9 |
10 | 所以,还在等什么?先右上角点个⭐️,再拿出手机📱扫码关注一波先~
11 |
12 | 
13 |
14 | ## 📑已发布文档索引
15 |
16 | ❤️❤️❤️持续更新中❤️❤️❤️
17 |
18 | ### JAVA精讲系列
19 |
20 | - 🔥[当JAVA注解、AOP、SpEL相遇,更多可能变为了现实 ](https://juejin.cn/post/7110920874412228639)
21 |
22 | - 🔥[为什么不建议使用自定义Object作为HashMap的key?](https://juejin.cn/post/7114555022599258119)
23 |
24 | - 🔥[避坑手册 | JAVA编码中容易踩坑的十大陷阱](https://juejin.cn/post/7114937973916827679)
25 |
26 | - 🔥[JAVA中简单的for循环竟有这么多坑,但愿你没踩过](https://juejin.cn/post/7117063647200804877)
27 |
28 | - 🔥[JAVA中计算两个日期时间的差值竟然也有这么多门道](https://juejin.cn/post/7117957247052808199)
29 |
30 | - 🔥🔥🔥[吃透JAVA的Stream流操作,多年实践总结](https://juejin.cn/post/7118991438448164878)
31 |
32 | - 🔥🔥[是时候优雅地和NullPointException说再见了](https://juejin.cn/post/7120131077502402567)
33 |
34 | - 🔥🔥🔥[讲透JAVA Stream的collect用法与原理,远比你想象的更强大](https://juejin.cn/post/7121539527151190053)
35 |
36 | - 🔥🔥🔥[JAVA基于CompletableFuture的流水线并行处理深度实践,满满干货](https://juejin.cn/post/7124124854747398175)
37 |
38 | - 🔥🔥🔥[不堆概念、换个角度聊JAVA多线程并发编程的防护策略](https://juejin.cn/post/7125356800055967752)
39 |
40 | - 🔥[聊聊Spring事务控制策略以及@Transactional失效问题避坑](https://juejin.cn/post/7129391912460484616)
41 |
42 | - 🔥🔥[用好JAVA中的函数式接口,轻松从通用代码中剥离掉业务定制逻辑](https://juejin.cn/post/7130573318549143588)
43 |
44 | - 🔥[JAVA中自定义扩展Swagger的能力,自动生成参数取值含义说明,提升开发效率](https://juejin.cn/post/7140042744671502343)
45 |
46 | - 🔥[JAVA中让Swagger产出更加符合我们诉求的描述文档,按需决定显示或者隐藏指定内容](https://juejin.cn/post/7140808845495894052)
47 |
48 | - 🔥🔥[JAVA中容器设计的进化史:从白盒到黑盒,再到跻身为设计模式之一的迭代器](https://juejin.cn/post/7146071733509750821)
49 |
50 | - 🔥🔥[编码中的Adapter,是一种设计模式,更是一种架构理念与解决方案](https://juejin.cn/post/7147846034931056677)
51 |
52 | ### 缓存系列专栏
53 |
54 | - 🔥🔥🔥[聊一聊作为高并发系统基石之一的缓存,会用很简单,用好才是技术活](https://juejin.cn/post/7151937376578142216)
55 |
56 | - 🔥🔥🔥[聊一聊安全且正确使用缓存的那些事 —— 关于缓存可靠性、关乎数据一致性](https://juejin.cn/post/7152670651302543397)
57 |
58 | - 🔥[手写本地缓存实战1——各个击破,按需应对实际使用场景](https://juejin.cn/post/7154212378316374030)
59 |
60 | - 🔥[手写本地缓存实战2—— 打造正规军,构建通用本地缓存框架](https://juejin.cn/post/7155278117479645221)
61 |
62 | - 🔥🔥[聊一聊JAVA中的缓存规范 —— 虽迟但到的JCache API与天生不俗的Spring Cache](https://juejin.cn/post/7159328581611421726)
63 |
64 | - 🔥[重新认识下JVM级别的本地缓存框架Guava Cache——优秀从何而来](https://juejin.cn/post/7160459619075096583)
65 |
66 | - 🔥[重新认识下JVM级别的本地缓存框架Guava Cache(2)——深入解读其容量限制与数据淘汰策略](https://juejin.cn/post/7161187654057328647)
67 |
68 | - 🔥[重新认识下JVM级别的本地缓存框架Guava Cache(3)——探寻实现细节与核心机制](https://juejin.cn/post/7163073153936130062)
69 |
70 | - 🔥🔥🔥[解读JVM级别本地缓存Caffeine青出于蓝的要诀 —— 缘何会更强、如何去上手](https://juejin.cn/post/7166020051059867661)
71 |
72 | - 🔥🔥[解读JVM级别本地缓存Caffeine青出于蓝的要诀2 —— 弄清楚Caffeine的同步、异步回源方式](https://juejin.cn/post/7166381015831674917)
73 |
74 | - 🔥🔥🔥[解读JVM级别本地缓存Caffeine青出于蓝的要诀3 —— 讲透Caffeine的数据驱逐淘汰机制与用法](https://juejin.cn/post/7166748976241180708)
75 |
76 | - 🔥🔥🔥[JAVA中使用最广泛的本地缓存?Ehcache的自信从何而来 —— 感受来自Ehcache的强大实力](https://juejin.cn/post/7167259989826863112)
77 |
78 | - 🔥🔥[JAVA中使用最广泛的本地缓存?Ehcache的自信从何而来2 —— Ehcache单独使用、基于JCache使用以及整合Spring中使用](https://juejin.cn/post/7168241367217340452)
79 |
80 | - 🔥🔥[JAVA中使用最广泛的本地缓存?Ehcache的自信从何而来3 —— 解析Ehcache的各种集群方案,本地缓存如何变身分布式缓存](https://juejin.cn/post/7168609036340822053)
81 |
82 | - 🔥🔥🔥[Redis缓存何以一枝独秀?——从百变应用场景与热门面试题中感受下Redis的核心特性与使用注意点](https://juejin.cn/post/7168986323754156069)
83 |
84 | - 🔥🔥[Redis缓存何以一枝独秀?(2) —— 聊聊Redis的数据过期、数据淘汰以及数据持久化的实现机制](https://juejin.cn/post/7169381569684373541)
85 |
86 | - 🔥[面对集中式缓存实现上的挑战,Redis交出的是何种答卷?聊聊Redis的主从、哨兵与集群部署模式](https://juejin.cn/post/7170836774917242893)
87 |
88 | - 🔥[探讨下如何更好的使用缓存 —— 集中式缓存Redis的BitMap存储、管道与事务、以及与本地缓存一起构建多级缓存](https://juejin.cn/post/7171575676061876231)
89 |
90 | ### Spring Data JPA系列
91 |
92 | - 🔥🔥[Spring Data JPA系列1:JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?给你讲透Spring Data JPA ](https://juejin.cn/post/7111551969281949733)
93 |
94 | - 🔥🔥[Spring Data JPA系列2:SpringBoot集成JPA详细教程,快速在项目中熟练使用JPA](https://juejin.cn/post/7112353499056177183)
95 |
96 | - 🔥🔥[Spring Data JPA系列3:JPA项目中核心场景与进阶用法介绍](https://juejin.cn/post/7112714785048756232)
97 |
98 | - 🔥[Spring Data JPA系列4——Spring声明式事务处理与多数据源支持](https://juejin.cn/post/7113170430726242317)
99 |
100 | - 🔥[Spring Data JPA系列5:让IDEA自动帮你写JPA实体定义代码【收官】](https://juejin.cn/post/7114215800008867871)
101 |
102 | ### 系统架构系列
103 |
104 | - 🔥🔥[基于开源方案构建统一的文件在线预览与office协同编辑平台的架构与实现历程](https://juejin.cn/post/7137096424797241352)
105 |
106 | - 🔥🔥🔥[搭建一个通用监控告警平台,架构上需要有哪些设计](https://juejin.cn/post/7115324928701759502)
107 |
108 | - 🔥🔥[我是如何将一个老系统的kafka消费者服务的性能提升近百倍的](https://juejin.cn/post/7116337330968854564)
109 |
110 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.veezean.java-basic-skills
8 | com.veezean
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 | org.apache.maven.plugins
14 | maven-compiler-plugin
15 |
16 | 8
17 | 8
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | org.projectlombok
29 | lombok
30 | 1.18.8
31 | provided
32 |
33 |
34 |
35 | javax.cache
36 | cache-api
37 | 1.1.1
38 |
39 |
40 |
41 | io.springfox
42 | springfox-swagger2
43 | 2.7.0
44 |
45 |
46 | io.springfox
47 | springfox-swagger-ui
48 | 2.7.0
49 |
50 |
51 |
52 | cn.hutool
53 | hutool-all
54 | 5.4.2
55 |
56 |
57 |
58 | com.alibaba
59 | fastjson
60 | 1.2.47
61 |
62 |
63 |
64 | com.fasterxml.jackson.core
65 | jackson-databind
66 | 2.5.0
67 |
68 |
69 |
70 | org.apache.commons
71 | commons-lang3
72 | 3.8.1
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | com.google.guava
82 | guava
83 | 31.1-jre
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | org.ehcache
95 | ehcache
96 | 3.9.5
97 |
98 |
99 |
100 | com.github.ben-manes.caffeine
101 | caffeine
102 | 2.9.3
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/src/main/java/com/veezean/skills/cache/CacheItem.java:
--------------------------------------------------------------------------------
1 | package com.veezean.skills.cache;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * <类功能简要描述>
7 | *
8 | * @author 架构悟道
9 | * @since 2022/10/13
10 | */
11 | @Data
12 | public class CacheItem {
13 | private V value;
14 | private long expireAt;
15 | // 后续有其它扩展,在此补充。。。
16 |
17 | public boolean hasExpired() {
18 | return System.currentTimeMillis() - expireAt > 0L;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/veezean/skills/cache/DemoCache.java:
--------------------------------------------------------------------------------
1 | package com.veezean.skills.cache;
2 |
3 | import java.util.*;
4 | import java.util.concurrent.ConcurrentHashMap;
5 | import java.util.concurrent.TimeUnit;
6 |
7 | /**
8 | * <类功能简要描述>
9 | *
10 | * @author 架构悟道
11 | * @since 2022/10/13
12 | */
13 | public class DemoCache {
14 | private Map> cache = new ConcurrentHashMap<>();
15 |
16 | public DemoCache() {
17 | timelyCleanExpiredItems();
18 | }
19 |
20 | /**
21 | * 单独设置某个key对应过期时间
22 | * @param key 唯一标识
23 | * @param timeIntvl 过期时间
24 | * @param timeUnit 时间单位
25 | */
26 | public void expireAfter(K key, int timeIntvl, TimeUnit timeUnit) {
27 | CacheItem item = cache.get(key);
28 | if (item == null) {
29 | return;
30 | }
31 | long expireAt = System.currentTimeMillis() + timeUnit.toMillis(timeIntvl);
32 | item.setExpireAt(expireAt);
33 | }
34 |
35 | /**
36 | * 写入指定过期时间的缓存信息
37 | * @param key 唯一标识
38 | * @param value 缓存实际值
39 | * @param timeIntvl 过期时间
40 | * @param timeUnit 时间单位
41 | */
42 | public void put(K key, V value, int timeIntvl, TimeUnit timeUnit) {
43 | long expireAt = System.currentTimeMillis() + timeUnit.toMillis(timeIntvl);
44 | CacheItem item = new CacheItem<>();
45 | item.setValue(value);
46 | item.setExpireAt(expireAt);
47 | cache.put(key, item);
48 | }
49 |
50 | /**
51 | * 从缓存中查询对应值
52 | * @param key 缓存key
53 | * @return 缓存值
54 | */
55 | public V get(K key) {
56 | CacheItem item = cache.get(key);
57 | if (item == null) {
58 | return null;
59 | }
60 | if (item.hasExpired()) {
61 | cache.remove(key);
62 | return null;
63 | }
64 | return item.getValue();
65 | }
66 |
67 | private void timelyCleanExpiredItems() {
68 | new Timer().schedule(new TimerTask() {
69 | @Override
70 | public void run() {
71 | cache.entrySet().removeIf(entry -> entry.getValue().hasExpired());
72 | }
73 | }, 1000L, 1000L * 60 * 60 *24);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/veezean/skills/cache/PostInfo.java:
--------------------------------------------------------------------------------
1 | package com.veezean.skills.cache;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * <类功能简要描述>
7 | *
8 | * @author 架构悟道
9 | * @since 2022/10/13
10 | */
11 | @Data
12 | public class PostInfo {
13 | private String id;
14 | private String title;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/veezean/skills/cache/PostService.java:
--------------------------------------------------------------------------------
1 | package com.veezean.skills.cache;
2 |
3 | import java.util.concurrent.TimeUnit;
4 |
5 | /**
6 | * <类功能简要描述>
7 | *
8 | * @author 架构悟道
9 | * @since 2022/10/13
10 | */
11 | public class PostService {
12 |
13 | private DemoCache cache = new DemoCache<>();
14 |
15 |
16 | public void sendPost(PostInfo post) {
17 | // ... 省略业务逻辑细节
18 | // 将新创建的帖子加入缓存中,缓存3分钟
19 | cache.put(post.getId(), post, 3, TimeUnit.MINUTES);
20 | }
21 |
22 | public PostInfo getPost(String postId) {
23 | PostInfo postInfo = cache.get(postId);
24 | if (postInfo != null) {
25 | // 每次使用后,都重新设置过期时间为3分钟后(续期)
26 | cache.expireAfter(postId, 3, TimeUnit.MINUTES);
27 | }
28 | return postInfo;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/veezean/skills/cache/caffeine/CaffeineCacheService.java:
--------------------------------------------------------------------------------
1 | package com.veezean.skills.cache.caffeine;
2 |
3 | import cn.hutool.core.util.RandomUtil;
4 | import com.github.benmanes.caffeine.cache.*;
5 | import com.veezean.skills.cache.guava.User;
6 |
7 | import java.util.List;
8 | import java.util.concurrent.CompletableFuture;
9 | import java.util.concurrent.Executors;
10 | import java.util.concurrent.TimeUnit;
11 |
12 | /**
13 | * <类功能简要描述>
14 | *
15 | * @author Wang Weiren
16 | * @since 2022/11/9
17 | */
18 | public class CaffeineCacheService {
19 |
20 | private static UserDao userDao = new UserDao();
21 | private static DepartmentDao departmentDao = new DepartmentDao();
22 |
23 | public LoadingCache createUserCache() {
24 | return Caffeine.newBuilder()
25 | .initialCapacity(1000)
26 | .maximumSize(10000L)
27 | .expireAfterWrite(30L, TimeUnit.MINUTES)
28 | // .concurrencyLevel(8)
29 | .recordStats()
30 | .build(key -> userDao.getUser(key));
31 | }
32 |
33 | public Cache createCache() {
34 | Cache cache = Caffeine.newBuilder()
35 | .executor(Executors.newFixedThreadPool(10))
36 | .expireAfterWrite(100L, TimeUnit.MILLISECONDS)
37 | .scheduler((executor, command, delay, unit) -> {
38 | System.out.println("scheduler executed...");
39 | System.out.println("command=" + command);
40 | System.out.println("delay=" + delay);
41 | System.out.println("unit=" + unit);
42 | return null;
43 | })
44 | .evictionListener((key, value, cause) -> {
45 | System.out.println(key + "被删除,原因:" + cause);
46 | })
47 | // .expireAfter(new Expiry() {
48 | //
49 | // @Override
50 | // public long expireAfterCreate(String key, String value, long currentTime) {
51 | // return TimeUnit.SECONDS.toNanos(1);
52 | // }
53 | //
54 | // @Override
55 | // public long expireAfterUpdate(String key, String value, long currentTime,
56 | // @NonNegative long currentDuration) {
57 | // System.out.println("currentDuration=" + currentDuration);
58 | // return currentDuration;
59 | // }
60 | //
61 | // @Override
62 | // public long expireAfterRead(String key, String value, long currentTime,
63 | // @NonNegative long currentDuration) {
64 | // return currentDuration;
65 | // }
66 | // })
67 | .build();
68 | return cache;
69 | }
70 |
71 | AsyncCache asyncCache = Caffeine.newBuilder().buildAsync();
72 |
73 | public boolean isDevUser(String userId) {
74 | // 获取用户信息
75 | CompletableFuture userFuture = asyncCache.get(userId, s -> userDao.getUser(s));
76 | // 获取公司研发体系部门列表
77 | CompletableFuture> devDeptFuture =
78 | CompletableFuture.supplyAsync(() -> departmentDao.getDevDepartments());
79 | // 等用户信息、研发部门列表都拉取完成后,判断用户是否属于研发体系
80 | CompletableFuture combineResult =
81 | userFuture.thenCombine(devDeptFuture,
82 | (user, devDepts) -> devDepts.contains(user.getDepartmentId()));
83 | // 等待执行完成,调用线程获取最终结果
84 | return combineResult.join();
85 | }
86 |
87 | public static AsyncLoadingCache buildAsyncLoadingCache() {
88 | return Caffeine.newBuilder()
89 | .initialCapacity(1000)
90 | .maximumSize(10000L)
91 | .expireAfterWrite(30L, TimeUnit.MINUTES)
92 | .refreshAfterWrite(1L, TimeUnit.MINUTES)
93 | .removalListener((key, value, cause) ->
94 | System.out.println(key + "移除,原因:" + cause))
95 | .recordStats()
96 | .buildAsync(key -> key + RandomUtil.randomString(5));
97 | }
98 |
99 | public static LoadingCache buildLoadingCache() {
100 | return Caffeine.newBuilder()
101 | .initialCapacity(1000)
102 | .maximumSize(10000L)
103 | .expireAfterWrite(30L, TimeUnit.MINUTES)
104 | .refreshAfterWrite(1L, TimeUnit.MINUTES)
105 | .removalListener((key, value, cause) ->
106 | System.out.println(key + "移除,原因:" + cause))
107 | .recordStats()
108 | .build(key -> key + RandomUtil.randomString(5));
109 | }
110 |
111 | // public static void main(String[] args) throws Exception {
112 | // AsyncLoadingCache asyncLoadingCache = buildAsyncLoadingCache();
113 | // asyncLoadingCache.put("key1", CompletableFuture.supplyAsync(() -> "value1"));
114 | // CompletableFuture completableFuture = asyncLoadingCache.get("key1");
115 | // String value = completableFuture.join();
116 | // System.out.println(value);
117 | // }
118 | public static void main(String[] args) throws Exception {
119 | LoadingCache loadingCache = buildLoadingCache();
120 | loadingCache.put("key1", "value1");
121 | String value = loadingCache.get("key1");
122 | System.out.println(value);
123 | }
124 | // try {
125 | //// CaffeineCacheService cacheService = new CaffeineCacheService();
126 | //// Cache cache = cacheService.createUserCache();
127 | //
128 | //
129 | // System.out.println("main thread:" + Thread.currentThread().getId());
130 | // // 同步方式
131 | // Cache cache = Caffeine.newBuilder().build();
132 | // cache.get("123", s -> {
133 | // System.out.println("同步callable thread:" + Thread.currentThread().getId());
134 | // return userDao.getUser(s);
135 | // });
136 | //// System.out.println(user);
137 | // // 异步方式
138 | // AsyncCache asyncCache = Caffeine.newBuilder().buildAsync();
139 | // asyncCache.get("123", s -> {
140 | // System.out.println("异步callable thread:" + Thread.currentThread().getId());
141 | // return userDao.getUser(s);
142 | // });
143 | // System.out.println(userCompletableFuture.join());
144 |
145 | // RepositoryId.cache.put("1", "111");
146 | // RepositoryId.cache.put("2", "222");
147 | // RepositoryId.cache.put("3", "333");
148 |
149 | // Thread.sleep(1000L);
150 | //
151 | // System.out.println("读取key2----" + RepositoryId.cache.getIfPresent("2"));
152 | // Thread.sleep(1000L);
153 |
154 | //
155 | // } catch (Exception e) {
156 | // e.printStackTrace();
157 | // }
158 |
159 | // try {
160 | // CaffeineCacheService cacheService = new CaffeineCacheService();
161 | // LoadingCache userCache = cacheService.createUserCache();
162 | // System.out.println(userCache.getClass().getCanonicalName());
163 |
164 | // LoadingCache cache = Caffeine.newBuilder().build(userId -> userDao.getUser(userId));
165 | // cache.put("124", new User("124", "张三"));
166 | // User user = cache.get("123");
167 | // System.out.println(user);
168 | // User techUser = cache.get("J234", userId -> {
169 | // // 仅J开头的用户ID才会去回源
170 | // if (!StringUtils.isEmpty(userId) && userId.startsWith("J")) {
171 | // return userDao.getUser(userId);
172 | // } else {
173 | // return null;
174 | // }
175 | // });
176 | // System.out.println(techUser);
177 |
178 | // User userInfo = cache.getIfPresent("123");
179 | // System.out.println(userInfo);
180 | // Map presentUsers =
181 | // cache.getAllPresent(Stream.of("123", "124", "125").collect(Collectors.toList()));
182 | // System.out.println(presentUsers);
183 | // } catch (Exception e) {
184 | // e.printStackTrace();
185 | // }
186 |
187 | // try {
188 | // AsyncCache asyncCache = Caffeine.newBuilder().buildAsync();
189 | // // 获取用户信息
190 | // CompletableFuture userFuture = asyncCache.get("123", s -> userDao.getUser(s));
191 | // // 获取公司研发体系部门列表
192 | // CompletableFuture> devDeptFuture =
193 | // CompletableFuture.supplyAsync(() -> departmentDao.getDevDepartments());
194 | // // 等用户信息、研发部门列表都拉取完成后,判断用户是否属于研发体系
195 | // CompletableFuture combineResult =
196 | // userFuture.thenCombine(devDeptFuture,
197 | // (user, devDepts) -> devDepts.contains(user.getDepartmentId()));
198 | // // 等待执行完成,调用线程获取最终结果
199 | // System.out.println("是否研发体系:" + combineResult.join());
200 | // } catch (Exception e) {
201 | // e.printStackTrace();
202 | // }
203 |
204 | // try {
205 | // AsyncLoadingCache asyncLoadingCache =
206 | // Caffeine.newBuilder().buildAsync(key -> userDao.getUser(key));
207 | // CompletableFuture userCompletableFuture = asyncLoadingCache.get("123");
208 | // System.out.println(userCompletableFuture.join());
209 | // } catch (Exception e) {
210 | // e.printStackTrace();
211 | // }
212 |
213 | // try {
214 | //
215 | // Cache