Skip to content

Commit 468b08e

Browse files
author
qiujiayu
committed
进一步优化“拿来主义”机制:使用当前的ProcessingTO来做同步锁,把锁粒度降到了最低,以提升并发性能;删除并发线程的计数器;如果第一个线程执行时出现异常,那等待中的线程,也直接抛出异常,因为此时去执行DAO的出错的可能性非常大,会造成服务器压力过大。
1 parent 1a40e74 commit 468b08e

File tree

5 files changed

+80
-61
lines changed

5 files changed

+80
-61
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,10 @@ web.xml配置:
434434

435435
## 更新日志
436436

437+
* ####3.2 进一步优化“拿来主义”机制
438+
439+
使用当前的ProcessingTO来做同步锁,把锁粒度降到了最低,以提升并发性能;删除并发线程的计数器;如果第一个线程执行时出现异常,那等待中的线程,也直接抛出异常,因为此时去执行DAO的出错的可能性非常大,会造成服务器压力过大。
440+
437441

438442
* ####3.1 优化“拿来主义”机制
439443

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<modelVersion>4.0.0</modelVersion>
33
<groupId>com.github.qiujiayu</groupId>
44
<artifactId>autoload-cache</artifactId>
5-
<version>3.1</version>
5+
<version>3.2</version>
66
<packaging>jar</packaging>
77
<name>AutoLoadCache</name>
88
<description>User Spring AOP and annotation to do with cache.</description>

src/main/java/com/jarvis/cache/AbstractCacheManager.java

Lines changed: 54 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ private CacheKeyTO getCacheKey(JoinPoint jp, CacheDeleteKey cacheDeleteKey, Obje
153153
* @return T 返回值
154154
* @throws Exception 异常
155155
*/
156-
public Object proceed(ProceedingJoinPoint pjp, Cache cache) throws Exception {
156+
public Object proceed(ProceedingJoinPoint pjp, Cache cache) throws Throwable {
157157
Object[] arguments=pjp.getArgs();
158158
// Signature signature=pjp.getSignature();
159159
// MethodSignature methodSignature=(MethodSignature)signature;
@@ -220,7 +220,7 @@ private CacheWrapper writeCache(Object result, CacheKeyTO cacheKey, int expire)
220220
* @return 返回值
221221
* @throws Exception
222222
*/
223-
private Object loadData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO, CacheKeyTO cacheKey, Cache cache) throws Exception {
223+
private Object loadData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO, CacheKeyTO cacheKey, Cache cache) throws Throwable {
224224
String fullKey=cacheKey.getFullKey();
225225
ProcessingTO isProcessing=processing.get(fullKey);
226226
ProcessingTO processingTO=null;
@@ -232,69 +232,74 @@ private Object loadData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO, CacheKey
232232
}
233233
}
234234
int expire=cache.expire();
235-
Object lock=pjp.getTarget();
235+
Object lock=null;
236236
Object result=null;
237-
try {
238-
// String tname=Thread.currentThread().getName();
239-
if(null == isProcessing) {
237+
238+
// String tname=Thread.currentThread().getName();
239+
if(null == isProcessing) {
240+
lock=processingTO;
241+
try {
240242
// System.out.println(tname + " first thread!");
241243
result=getData(pjp, autoLoadTO);
242244
CacheWrapper cacheWrapper=writeCache(result, cacheKey, expire);
243245
processingTO.setCache(cacheWrapper);// 本地缓存
244-
} else {
245-
isProcessing.getCounter().incrementAndGet();
246-
long startWait=System.currentTimeMillis();
247-
CacheWrapper cacheWrapper=null;
248-
while(System.currentTimeMillis() - startWait < cache.waitTimeOut()) {// 等待
249-
if(null == isProcessing) {
250-
break;
246+
} catch(Throwable e) {
247+
processingTO.setError(e);
248+
throw e;
249+
} finally {
250+
processingTO.setFirstFinished(true);
251+
processing.remove(fullKey);
252+
synchronized(lock) {
253+
lock.notifyAll();
254+
}
255+
}
256+
} else {
257+
lock=isProcessing;
258+
long startWait=isProcessing.getStartTime();
259+
CacheWrapper cacheWrapper=null;
260+
do {// 等待
261+
if(null == isProcessing) {
262+
break;
263+
}
264+
if(isProcessing.isFirstFinished()) {
265+
// System.out.println(tname + " FirstFinished");
266+
cacheWrapper=isProcessing.getCache();// 从本地缓存获取数据, 防止频繁去缓存服务器取数据,造成缓存服务器压力过大
267+
if(null != cacheWrapper) {
268+
// System.out.println(tname + " do 222" + " is null :" + (null == cacheWrapper));
269+
return cacheWrapper.getCacheObject();
251270
}
252-
if(isProcessing.isFirstFinished()) {
253-
// System.out.println(tname + " FirstFinished");
254-
cacheWrapper=isProcessing.getCache();// 从本地缓存获取数据, 防止频繁去缓存服务器取数据,造成缓存服务器压力过大
255-
if(null != cacheWrapper) {
256-
// System.out.println(tname + " do 222" + " is null :" + (null == cacheWrapper));
257-
return cacheWrapper.getCacheObject();
258-
}
259-
} else {
260-
synchronized(lock) {
261-
// System.out.println(tname + " do 333");
262-
try {
263-
lock.wait(50);// 测试lock对象是否有效,wait的时候去掉就可以
264-
} catch(InterruptedException ex) {
265-
logger.error(ex.getMessage(), ex);
266-
}
271+
Throwable error=isProcessing.getError();
272+
if(null != error) {// 当DAO出错时,直接抛异常
273+
throw error;
274+
}
275+
break;
276+
} else {
277+
synchronized(lock) {
278+
// System.out.println(tname + " do 333");
279+
try {
280+
lock.wait(50);// 如果要测试lock对象是否有效,wait时间去掉就可以
281+
} catch(InterruptedException ex) {
282+
logger.error(ex.getMessage(), ex);
267283
}
268284
}
269285
}
286+
} while(System.currentTimeMillis() - startWait < cache.waitTimeOut());
287+
try {
270288
result=getData(pjp, autoLoadTO);
271289
writeCache(result, cacheKey, expire);
272-
}
273-
} catch(Exception e) {
274-
throw e;
275-
} catch(Throwable e) {
276-
throw new Exception(e);
277-
} finally {
278-
if(null != processingTO) {
279-
processingTO.setFirstFinished(true);
280-
}
281-
isProcessing=processing.get(fullKey);
282-
if(null == isProcessing) {
283-
processing.remove(fullKey);
284-
} else {
285-
int cnt=isProcessing.getCounter().decrementAndGet();
286-
if(cnt == 0) {
287-
processing.remove(fullKey);
290+
} catch(Throwable e) {
291+
throw e;
292+
} finally {
293+
synchronized(lock) {
294+
lock.notifyAll();
288295
}
289296
}
290-
synchronized(lock) {
291-
lock.notifyAll();
292-
}
293297
}
298+
294299
return result;
295300
}
296301

297-
private Object getData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO) throws Exception {
302+
private Object getData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO) throws Throwable {
298303
try {
299304
if(null != autoLoadTO) {
300305
autoLoadTO.setLoading(true);
@@ -312,10 +317,8 @@ private Object getData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO) throws Ex
312317
autoLoadTO.addUseTotalTime(useTime);
313318
}
314319
return result;
315-
} catch(Exception e) {
316-
throw e;
317320
} catch(Throwable e) {
318-
throw new Exception(e);
321+
throw e;
319322
} finally {
320323
if(null != autoLoadTO) {
321324
autoLoadTO.setLoading(false);

src/main/java/com/jarvis/cache/mybatis/CachePointCutProxy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public void setCacheManager(AbstractCacheManager cacheManager) {
2828
this.cacheManager=cacheManager;
2929
}
3030

31-
public Object proceed(ProceedingJoinPoint pjp) throws Exception {
31+
public Object proceed(ProceedingJoinPoint pjp) throws Throwable {
3232
Signature signature=pjp.getSignature();
3333
MethodSignature methodSignature=(MethodSignature)signature;
3434
Method method=methodSignature.getMethod();

src/main/java/com/jarvis/cache/to/ProcessingTO.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
package com.jarvis.cache.to;
22

3-
import java.util.concurrent.atomic.AtomicInteger;
4-
53
public class ProcessingTO {
64

7-
private AtomicInteger counter=new AtomicInteger(0);
5+
private long startTime;
86

97
private CacheWrapper cache;
108

119
private boolean firstFinished=false;
1210

13-
public AtomicInteger getCounter() {
14-
return counter;
15-
}
11+
private Throwable error;
1612

17-
public void setCounter(AtomicInteger counter) {
18-
this.counter=counter;
13+
public ProcessingTO() {
14+
startTime=System.currentTimeMillis();
1915
}
2016

2117
public CacheWrapper getCache() {
@@ -34,4 +30,20 @@ public void setFirstFinished(boolean firstFinished) {
3430
this.firstFinished=firstFinished;
3531
}
3632

33+
public long getStartTime() {
34+
return startTime;
35+
}
36+
37+
public void setStartTime(long startTime) {
38+
this.startTime=startTime;
39+
}
40+
41+
public Throwable getError() {
42+
return error;
43+
}
44+
45+
public void setError(Throwable error) {
46+
this.error=error;
47+
}
48+
3749
}

0 commit comments

Comments
 (0)