我正在尝试使我的http会话刷新功能同步。我正在使用rxjava和改型。为了简单起见,这是我的函数,其中包含一些代码:
public void refreshSession(){
fetchNewSession(...).flatMap(response -> {
if(response.isSuccessful()) {
storeNewSessionId(response.headers().get("sessionId"));
return Observable.empty();
} else {
throw new MyHTTPException(response);
}
}).doOnError(throwable -> {
Thread.currentThread().interupt();
}).blockingSubscribe();
}
所以我要做的是同步这个函数,这样只有一个线程获取新会话,而其他线程等待。这是我试图实现的一些伪代码:
public void refreshSession(){
if(!sessionNotRefreshed){
fetchNewSession();
} else {
wait();
}
}
因此,当新的http请求与过期的会话一起发送时,我得到的响应是会话无效,并阻塞线程,直到会话被刷新,之后http请求将与刷新的会话一起重新发送。我尝试了以下方法(这可能是非常错误的,joshua bloch在他的书effective java programming中说,我们应该使用一些更高级的api来通知和等待):
private final Object LOCK = new Object();
private volotile booleand sessionRefreshed = true;
public void refreshSession(){
try {
if(!sessionRefreshed){
synchronized(LOCK){
LOCK.wait();
}
} else {
sessionRenewed = false;
fetchNewSession(...).flatMap(response -> {
if(response.isSuccessful()) {
storeNewSessionId(response.headers().get("sessionId"));
return Observable.empty();
} else {
throw new MyHTTPException(response);
}
}).doOnError(throwable -> {
Thread.currentThread().interupt();
}).blockingSubscribe();
}
} finally {
synchronized (LOCK) {
LOCK.notifyAll();
}
sessionRenewed = true;
}
}
还有这个:
private final CountDownLatch LOCK = new CountDownLatch(1);
private volotile booleand sessionRefreshed = false;
public void refreshSession(){
if(!sessionRefreshed){
sessionRenewed = true;
fetchNewSession(...).flatMap(response -> {
if(response.isSuccessful()) {
storeNewSessionId(response.headers().get("sessionId"));
return Observable.empty();
} else {
throw new MyHTTPException(response);
}
}).doOnError(throwable -> {
Thread.currentThread().interupt();
}).blockingSubscribe();
LOCK.countDown();
sessionRefreshed = false;
} else {
LOCK.await();
}
}
但这只适用于线程的第一次调用,因为计数达到0。我可以在 LOCK = new CountDownLatch(1);
但我认为倒计时锁不适合这样的事情。有condition和reentrantlock api以及phaser api,但我不知道如何使用它们。我也尝试不同步:
private final CountDownLatch LOCK = new CountDownLatch(1);
private volotile booleand sessionRefreshed = false;
public void refreshSession(){
if(!sessionRefreshed){
sessionRenewed = true;
fetchNewSession(...).flatMap(response -> {
if(response.isSuccessful()) {
storeNewSessionId(response.headers().get("sessionId"));
return Observable.empty();
} else {
throw new MyHTTPException(response);
}
}).doOnError(throwable -> {
Thread.currentThread().interupt();
}).blockingSubscribe();
Schedulers.io().createWorker().schedule(() -> {
sessionRefreshed = false;
}, 5, TimeUnit.SECONDS);
} else {
}
}
不允许多个线程在5秒内同时获取会话。这些都正确吗?有更好的解决方案吗?
暂无答案!
目前还没有任何答案,快来回答吧!