我有一个可以同时访问某个资源的Spring Web应用程序。此资源包含可能由请求获取的某些对象的列表。如果列表为空,则不应再返回任何SomeClass对象
资源如下所示:
public class Resource {
private List<SomeClass> someList;
public List<SomeClass> fetch() {
List<SomeClass> fetched = new ArrayList<SomeClass>();
int max = someList.size();
if(max<=0) {
return fetched;
}
int added = 0;
while(added<max) {
int randomIndex = Math.random(max-1);
SomeClass someClass = someList.get(randomIndex);
if(!fetched.contains(someClass)) {
fetched.add(someClass);
++added;
}
}
someList.remove(fetched);
return fetched;
}
}
此资源加载到服务层,然后访问并保存回数据库:
@Service
public class ResourceService {
@Autowired
private ResourceRepository repo;
public List<SomeClass> fetch(long id) {
Resource resource = repo.findOne(id);
List<SomeClass> fetched = resource.fetch();
repo.save(resource);
return fetched;
}
}
我尝试在ResourceService #fetch方法上使用@Transactional来避免两个并发请求可能从列表中获取SomeClass对象的问题,尽管第一个请求已经清空了列表,但我不确定这是否是正确的方法......我是否必须在Resource#fetch方法上使用@Synchronized或在服务层中引入显式锁?
我需要确保只有一个请求正在访问资源(获取SomeClass对象的列表)而不会抛出异常。相反,后续请求应排队并在当前请求完成获取SomeClass对象列表后尝试访问资源。
答案 0 :(得分:0)
我的最终解决方案是在@Service中引入Blocking Queue并将所有传入请求添加到它。然后,只要添加一个元素并对其进行处理,单独的线程就是taking队列中的元素。
我认为这是最干净的解决方案,因为添加ReentrantLock会阻止请求处理。