我有一个访问缓存的Jersey REST服务方法。此方法跟踪requestsBeingProcessed
,因为MessageService
会定期更新缓存,但是只有在没有正在处理的请求时才可以这样做。递增和递减正在处理的请求数的调用是同步的,以确保线程安全的访问。
class TeamInfoService {
@GET
@Path("/{teamId}")
@Produces(MediaType.TEXT_PLAIN)
public String getTeamInfo(@PathParam("teamId") final int teamId) {
MessageService.incrementRequestsBeingProcessed;
String team = teamCache.getTeams().get(teamId);
MessageService.decrementRequestsBeingProcessed;
return team;
}
}
class MessageService {
private static int requestsBeingProcessed = 0;
public synchronized static void incrementRequestsBeingProcessed() {
requestsBeingProcessed++;
}
public synchronized static void decrementRequestsBeingProcessed() {
requestsBeingProcessed--;
}
public synchronized static void getRequestsBeingProcessed() {
return requestsBeingProcessed;
}
}
问题在于
MessageService
必须获取锁才能更新缓存,但是只能通过检查requestsBeingProcessed
来更新它,一次只能由一个线程访问。public synchronized static void updateCache(String message) {
while(getRequestsBeingProcessed() != 0) {
//wait until there are no requests being processed
}
processMessage(message);
}
我在这里遇到了鸡/蛋的情况:我无法获取更新
requestsBeingProcessed
的锁,因为需要使用锁来检查requestsBeingProcessed
。我应该采用其他方法解决这个问题吗? 最佳答案
每当队列中没有任何项目时,您需要通知更新线程:
public synchronized static void decrementRequestsBeingProcessed() {
if (requestsBeingProcessed > 0) requestsBeingProcessed--;
if (requestsBeingProcessed == 0) MessageService.class.notifyAll();
}
public synchronized static void updateCache(String message) {
try {
while(getRequestsBeingProcessed() != 0) {
MessageService.class.wait();
}
processMessage(message);
} catch (InterruptedException ie) {
// devise cancellation strategy here...
}
}