Skip to content

Commit

Permalink
进一步优化“拿来主义”机制:使用当前的ProcessingTO来做同步锁,把锁粒度降到了最低,以提升并发性能;删除并发线程的计数器;如果第…
Browse files Browse the repository at this point in the history
…一个线程执行时出现异常,那等待中的线程,也直接抛出异常,因为此时去执行DAO的出错的可能性非常大,会造成服务器压力过大。
  • Loading branch information
qiujiayu committed Feb 22, 2016
1 parent 1a40e74 commit 468b08e
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 61 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,10 @@ web.xml配置:

## 更新日志

* ####3.2 进一步优化“拿来主义”机制

使用当前的ProcessingTO来做同步锁,把锁粒度降到了最低,以提升并发性能;删除并发线程的计数器;如果第一个线程执行时出现异常,那等待中的线程,也直接抛出异常,因为此时去执行DAO的出错的可能性非常大,会造成服务器压力过大。


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

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.qiujiayu</groupId>
<artifactId>autoload-cache</artifactId>
<version>3.1</version>
<version>3.2</version>
<packaging>jar</packaging>
<name>AutoLoadCache</name>
<description>User Spring AOP and annotation to do with cache.</description>
Expand Down
105 changes: 54 additions & 51 deletions src/main/java/com/jarvis/cache/AbstractCacheManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ private CacheKeyTO getCacheKey(JoinPoint jp, CacheDeleteKey cacheDeleteKey, Obje
* @return T 返回值
* @throws Exception 异常
*/
public Object proceed(ProceedingJoinPoint pjp, Cache cache) throws Exception {
public Object proceed(ProceedingJoinPoint pjp, Cache cache) throws Throwable {
Object[] arguments=pjp.getArgs();
// Signature signature=pjp.getSignature();
// MethodSignature methodSignature=(MethodSignature)signature;
Expand Down Expand Up @@ -220,7 +220,7 @@ private CacheWrapper writeCache(Object result, CacheKeyTO cacheKey, int expire)
* @return 返回值
* @throws Exception
*/
private Object loadData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO, CacheKeyTO cacheKey, Cache cache) throws Exception {
private Object loadData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO, CacheKeyTO cacheKey, Cache cache) throws Throwable {
String fullKey=cacheKey.getFullKey();
ProcessingTO isProcessing=processing.get(fullKey);
ProcessingTO processingTO=null;
Expand All @@ -232,69 +232,74 @@ private Object loadData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO, CacheKey
}
}
int expire=cache.expire();
Object lock=pjp.getTarget();
Object lock=null;
Object result=null;
try {
// String tname=Thread.currentThread().getName();
if(null == isProcessing) {

// String tname=Thread.currentThread().getName();
if(null == isProcessing) {
lock=processingTO;
try {
// System.out.println(tname + " first thread!");
result=getData(pjp, autoLoadTO);
CacheWrapper cacheWrapper=writeCache(result, cacheKey, expire);
processingTO.setCache(cacheWrapper);// 本地缓存
} else {
isProcessing.getCounter().incrementAndGet();
long startWait=System.currentTimeMillis();
CacheWrapper cacheWrapper=null;
while(System.currentTimeMillis() - startWait < cache.waitTimeOut()) {// 等待
if(null == isProcessing) {
break;
} catch(Throwable e) {
processingTO.setError(e);
throw e;
} finally {
processingTO.setFirstFinished(true);
processing.remove(fullKey);
synchronized(lock) {
lock.notifyAll();
}
}
} else {
lock=isProcessing;
long startWait=isProcessing.getStartTime();
CacheWrapper cacheWrapper=null;
do {// 等待
if(null == isProcessing) {
break;
}
if(isProcessing.isFirstFinished()) {
// System.out.println(tname + " FirstFinished");
cacheWrapper=isProcessing.getCache();// 从本地缓存获取数据, 防止频繁去缓存服务器取数据,造成缓存服务器压力过大
if(null != cacheWrapper) {
// System.out.println(tname + " do 222" + " is null :" + (null == cacheWrapper));
return cacheWrapper.getCacheObject();
}
if(isProcessing.isFirstFinished()) {
// System.out.println(tname + " FirstFinished");
cacheWrapper=isProcessing.getCache();// 从本地缓存获取数据, 防止频繁去缓存服务器取数据,造成缓存服务器压力过大
if(null != cacheWrapper) {
// System.out.println(tname + " do 222" + " is null :" + (null == cacheWrapper));
return cacheWrapper.getCacheObject();
}
} else {
synchronized(lock) {
// System.out.println(tname + " do 333");
try {
lock.wait(50);// 测试lock对象是否有效,wait的时候去掉就可以
} catch(InterruptedException ex) {
logger.error(ex.getMessage(), ex);
}
Throwable error=isProcessing.getError();
if(null != error) {// 当DAO出错时,直接抛异常
throw error;
}
break;
} else {
synchronized(lock) {
// System.out.println(tname + " do 333");
try {
lock.wait(50);// 如果要测试lock对象是否有效,wait时间去掉就可以
} catch(InterruptedException ex) {
logger.error(ex.getMessage(), ex);
}
}
}
} while(System.currentTimeMillis() - startWait < cache.waitTimeOut());
try {
result=getData(pjp, autoLoadTO);
writeCache(result, cacheKey, expire);
}
} catch(Exception e) {
throw e;
} catch(Throwable e) {
throw new Exception(e);
} finally {
if(null != processingTO) {
processingTO.setFirstFinished(true);
}
isProcessing=processing.get(fullKey);
if(null == isProcessing) {
processing.remove(fullKey);
} else {
int cnt=isProcessing.getCounter().decrementAndGet();
if(cnt == 0) {
processing.remove(fullKey);
} catch(Throwable e) {
throw e;
} finally {
synchronized(lock) {
lock.notifyAll();
}
}
synchronized(lock) {
lock.notifyAll();
}
}

return result;
}

private Object getData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO) throws Exception {
private Object getData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO) throws Throwable {
try {
if(null != autoLoadTO) {
autoLoadTO.setLoading(true);
Expand All @@ -312,10 +317,8 @@ private Object getData(ProceedingJoinPoint pjp, AutoLoadTO autoLoadTO) throws Ex
autoLoadTO.addUseTotalTime(useTime);
}
return result;
} catch(Exception e) {
throw e;
} catch(Throwable e) {
throw new Exception(e);
throw e;
} finally {
if(null != autoLoadTO) {
autoLoadTO.setLoading(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public void setCacheManager(AbstractCacheManager cacheManager) {
this.cacheManager=cacheManager;
}

public Object proceed(ProceedingJoinPoint pjp) throws Exception {
public Object proceed(ProceedingJoinPoint pjp) throws Throwable {
Signature signature=pjp.getSignature();
MethodSignature methodSignature=(MethodSignature)signature;
Method method=methodSignature.getMethod();
Expand Down
28 changes: 20 additions & 8 deletions src/main/java/com/jarvis/cache/to/ProcessingTO.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
package com.jarvis.cache.to;

import java.util.concurrent.atomic.AtomicInteger;

public class ProcessingTO {

private AtomicInteger counter=new AtomicInteger(0);
private long startTime;

private CacheWrapper cache;

private boolean firstFinished=false;

public AtomicInteger getCounter() {
return counter;
}
private Throwable error;

public void setCounter(AtomicInteger counter) {
this.counter=counter;
public ProcessingTO() {
startTime=System.currentTimeMillis();
}

public CacheWrapper getCache() {
Expand All @@ -34,4 +30,20 @@ public void setFirstFinished(boolean firstFinished) {
this.firstFinished=firstFinished;
}

public long getStartTime() {
return startTime;
}

public void setStartTime(long startTime) {
this.startTime=startTime;
}

public Throwable getError() {
return error;
}

public void setError(Throwable error) {
this.error=error;
}

}

0 comments on commit 468b08e

Please sign in to comment.