Skip to content

Commit b2234f5

Browse files
committed
fix cache
1 parent 927dc14 commit b2234f5

File tree

10 files changed

+188
-21
lines changed

10 files changed

+188
-21
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
## 4.5.16
77

88
### 新特性
9+
* 【cache】 缓存增加get重载(pr#404@Github)
910

1011
### Bug修复
1112

hutool-cache/src/main/java/cn/hutool/cache/Cache.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.Iterator;
44

55
import cn.hutool.cache.impl.CacheObj;
6+
import cn.hutool.core.lang.func.Func0;
67

78
/**
89
* 缓存接口
@@ -60,6 +61,15 @@ public interface Cache<K, V> extends Iterable<V> {
6061
* @see #get(Object, boolean)
6162
*/
6263
V get(K key);
64+
65+
/**
66+
* 从缓存中获得对象,当对象不在缓存中或已经过期返回Func0回调产生的对象
67+
*
68+
* @param key 键
69+
* @param supplier 如果不存在回调方法,用于生产值对象
70+
* @return 值对象
71+
*/
72+
V get(K key, Func0<V> supplier);
6373

6474
/**
6575
* 从缓存中获得对象,当对象不在缓存中或已经过期返回<code>null</code>

hutool-cache/src/main/java/cn/hutool/cache/impl/AbstractCache.java

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import cn.hutool.cache.Cache;
1010
import cn.hutool.core.collection.CopiedIter;
11+
import cn.hutool.core.lang.func.Func0;
1112

1213
/**
1314
* 超时和限制大小的缓存的默认实现<br>
@@ -54,18 +55,30 @@ public void put(K key, V object, long timeout) {
5455
writeLock.lock();
5556

5657
try {
57-
CacheObj<K, V> co = new CacheObj<K, V>(key, object, timeout);
58-
if (timeout != 0) {
59-
existCustomTimeout = true;
60-
}
61-
if (isFull()) {
62-
pruneCache();
63-
}
64-
cacheMap.put(key, co);
58+
putWithoutLock(key, object, timeout);
6559
} finally {
6660
writeLock.unlock();
6761
}
6862
}
63+
64+
/**
65+
* 加入元素,无锁
66+
*
67+
* @param key 键
68+
* @param object 值
69+
* @param timeout 超时时长
70+
* @since 4.5.16
71+
*/
72+
private void putWithoutLock(K key, V object, long timeout) {
73+
CacheObj<K, V> co = new CacheObj<K, V>(key, object, timeout);
74+
if (timeout != 0) {
75+
existCustomTimeout = true;
76+
}
77+
if (isFull()) {
78+
pruneCache();
79+
}
80+
cacheMap.put(key, co);
81+
}
6982
// ---------------------------------------------------------------- put end
7083

7184
// ---------------------------------------------------------------- get start
@@ -122,6 +135,31 @@ public V get(K key) {
122135
return get(key, true);
123136
}
124137

138+
@Override
139+
public V get(K key, Func0<V> supplier) {
140+
V v = get(key);
141+
if (null == v && null != supplier) {
142+
writeLock.lock();
143+
try {
144+
// 双重检查锁
145+
final CacheObj<K, V> co = cacheMap.get(key);
146+
if(null == co || co.isExpired() || null == co.getValue()) {
147+
try {
148+
v = supplier.call();
149+
} catch (Exception e) {
150+
throw new RuntimeException(e);
151+
}
152+
putWithoutLock(key, v, this.timeout);
153+
} else {
154+
v = co.get(true);
155+
}
156+
} finally {
157+
writeLock.unlock();
158+
}
159+
}
160+
return v;
161+
}
162+
125163
@Override
126164
public V get(K key, boolean isUpdateLastAccess) {
127165
readLock.lock();
@@ -133,7 +171,7 @@ public V get(K key, boolean isUpdateLastAccess) {
133171
missCount++;
134172
return null;
135173
}
136-
174+
137175
if (false == co.isExpired()) {
138176
// 命中
139177
hitCount++;
@@ -293,15 +331,27 @@ private void remove(K key, boolean withMissCount) {
293331
writeLock.lock();
294332
CacheObj<K, V> co;
295333
try {
296-
co = cacheMap.remove(key);
297-
if (withMissCount) {
298-
this.missCount--;
299-
}
334+
co = removeWithoutLock(key, withMissCount);
300335
} finally {
301336
writeLock.unlock();
302337
}
303338
if (null != co) {
304339
onRemove(co.key, co.obj);
305340
}
306341
}
342+
343+
/**
344+
* 移除key对应的对象,不加锁
345+
*
346+
* @param key 键
347+
* @param withMissCount 是否计数丢失数
348+
* @return 移除的对象,无返回null
349+
*/
350+
private CacheObj<K, V> removeWithoutLock(K key, boolean withMissCount) {
351+
final CacheObj<K, V> co = cacheMap.remove(key);
352+
if (withMissCount) {
353+
this.missCount--;
354+
}
355+
return co;
356+
}
307357
}

hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObj.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ V get(boolean isUpdateLastAccess) {
6161
lastAccess = System.currentTimeMillis();
6262
}
6363
accessCount++;
64-
return obj;
64+
return this.obj;
6565
}
6666

6767
/**

hutool-cache/src/main/java/cn/hutool/cache/impl/NoCache.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.Iterator;
44

55
import cn.hutool.cache.Cache;
6+
import cn.hutool.core.lang.func.Func0;
67

78
/**
89
* 无缓存实现,用于快速关闭缓存
@@ -47,6 +48,15 @@ public V get(K key) {
4748
public V get(K key, boolean isUpdateLastAccess) {
4849
return null;
4950
}
51+
52+
@Override
53+
public V get(K key, Func0<V> supplier) {
54+
try {
55+
return (null == supplier) ? null : supplier.call();
56+
} catch (Exception e) {
57+
throw new RuntimeException(e);
58+
}
59+
}
5060

5161
@Override
5262
public Iterator<V> iterator() {

hutool-cache/src/test/java/cn/hutool/cache/test/CacheTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import cn.hutool.cache.CacheUtil;
88
import cn.hutool.cache.impl.TimedCache;
99
import cn.hutool.core.date.DateUnit;
10+
import cn.hutool.core.lang.func.Func0;
1011
import cn.hutool.core.thread.ThreadUtil;
1112

1213
/**
@@ -91,6 +92,15 @@ public void timedCacheTest(){
9192
String value3 = timedCache.get("key3");
9293
Assert.assertTrue(null == value3);
9394

95+
String value3Supplier = timedCache.get("key3", new Func0<String>() {
96+
97+
@Override
98+
public String call() throws Exception {
99+
return "Default supplier";
100+
}
101+
});
102+
Assert.assertEquals("Default supplier", value3Supplier);
103+
94104
// 永不过期
95105
String value4 = timedCache.get("key4");
96106
Assert.assertEquals("value4", value4);

hutool-core/src/main/java/cn/hutool/core/lang/SimpleCache.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
77
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
88

9+
import cn.hutool.core.lang.func.Func0;
10+
911
/**
1012
* 简单缓存,无超时实现,使用{@link WeakHashMap}实现缓存自动清理
1113
* @author Looly
@@ -39,6 +41,35 @@ public V get(K key) {
3941
return value;
4042
}
4143

44+
/**
45+
* 从缓存中获得对象,当对象不在缓存中或已经过期返回Func0回调产生的对象
46+
*
47+
* @param key 键
48+
* @param supplier 如果不存在回调方法,用于生产值对象
49+
* @return 值对象
50+
*/
51+
public V get(K key, Func0<V> supplier) {
52+
V v = get(key);
53+
if (null == v && null != supplier) {
54+
writeLock.lock();
55+
try {
56+
// 双重检查锁
57+
v = cache.get(key);
58+
if(null == v) {
59+
try {
60+
v = supplier.call();
61+
} catch (Exception e) {
62+
throw new RuntimeException(e);
63+
}
64+
cache.put(key, v);
65+
}
66+
} finally {
67+
writeLock.unlock();
68+
}
69+
}
70+
return v;
71+
}
72+
4273
/**
4374
* 放入缓存
4475
* @param key 键

hutool-poi/src/main/java/cn/hutool/poi/excel/StyleSet.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,25 @@ public StyleSet setFont(short color, short fontSize, String fontName, boolean ig
160160
* @since 4.1.0
161161
*/
162162
public StyleSet setFont(Font font, boolean ignoreHead) {
163-
if(false == ignoreHead) {
163+
if (false == ignoreHead) {
164164
this.headCellStyle.setFont(font);
165165
}
166166
this.cellStyle.setFont(font);
167167
this.cellStyleForNumber.setFont(font);
168168
this.cellStyleForDate.setFont(font);
169169
return this;
170170
}
171+
172+
/**
173+
* 设置单元格文本自动换行
174+
*
175+
* @return this
176+
* @since 4.5.16
177+
*/
178+
public StyleSet setWrapText() {
179+
this.cellStyle.setWrapText(true);
180+
this.cellStyleForNumber.setWrapText(true);
181+
this.cellStyleForDate.setWrapText(true);
182+
return this;
183+
}
171184
}

hutool-poi/src/main/java/cn/hutool/poi/word/Word07Writer.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class Word07Writer implements Closeable {
3535
public Word07Writer() {
3636
this(new XWPFDocument());
3737
}
38-
38+
3939
/**
4040
* 构造
4141
*
@@ -44,7 +44,7 @@ public Word07Writer() {
4444
public Word07Writer(File destFile) {
4545
this(DocUtil.create(destFile), destFile);
4646
}
47-
47+
4848
/**
4949
* 构造
5050
*
@@ -53,7 +53,7 @@ public Word07Writer(File destFile) {
5353
public Word07Writer(XWPFDocument doc) {
5454
this(doc, null);
5555
}
56-
56+
5757
/**
5858
* 构造
5959
*
@@ -64,7 +64,7 @@ public Word07Writer(XWPFDocument doc, File destFile) {
6464
this.doc = doc;
6565
this.destFile = destFile;
6666
}
67-
67+
6868
// -------------------------------------------------------------------------- Constructor end
6969

7070
/**
@@ -75,7 +75,7 @@ public Word07Writer(XWPFDocument doc, File destFile) {
7575
public XWPFDocument getDoc() {
7676
return this.doc;
7777
}
78-
78+
7979
/**
8080
* 设置写出的目标文件
8181
*
@@ -126,7 +126,19 @@ public Word07Writer addText(ParagraphAlignment align, Font font, String... texts
126126
}
127127
return this;
128128
}
129-
129+
130+
/**
131+
* 增加表格数据
132+
*
133+
* @param data 表格数据,多行数据。元素表示一行数据,当为集合或者数组时,为一行;当为Map或者Bean时key表示标题,values为数据
134+
* @return this
135+
* @since 4.5.16
136+
*/
137+
public Word07Writer addTable(Iterable<?> data) {
138+
TableUtil.createTable(this.doc, data);
139+
return this;
140+
}
141+
130142
/**
131143
* 将Excel Workbook刷出到预定义的文件<br>
132144
* 如果用户未自定义输出的文件,将抛出{@link NullPointerException}<br>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package cn.hutool.poi.word;
2+
3+
import java.io.File;
4+
5+
/**
6+
* Word工具类
7+
*
8+
* @author Looly
9+
* @since 4.5.16
10+
*/
11+
public class WordUtil {
12+
/**
13+
* 创建Word 07格式的生成器
14+
*
15+
* @return {@link Word07Writer}
16+
*/
17+
public static Word07Writer getWriter() {
18+
return new Word07Writer();
19+
}
20+
21+
/**
22+
* 创建Word 07格式的生成器
23+
*
24+
* @param destFile 目标文件
25+
* @return {@link Word07Writer}
26+
*/
27+
public static Word07Writer getWriter(File destFile) {
28+
return new Word07Writer(destFile);
29+
}
30+
}

0 commit comments

Comments
 (0)