I want to build a repository class, as follows:
public class ResultRepository {
private Map<String, Result> sqlRepository = Collections.synchronizedMap(new HashMap<>());
public synchronized Result getResult(String key) {
Result result = map.get(key);
if (result == null) {
result = doAnExpensiveOperation(key));
map.put(key, result);
}
return result;
}
...
}
This will work, currently, but will be slow if multiple calls are made to the getResult
method if the expensive operation is required.
What I want, however, is this:
- Retrieving the result for different keys is non-blocking
- If the result for a specific key has already been created, it is returned immediately
- If the result for a specific key has not already been created, it is generated (via the expensive operation)
- If the result for a specific key has not already been created, but is being generated in a separate thread, the thread waits until the results are created and then returns this.
Is there a pattern I can apply to get this behaviour? I could theoretically have a Set
of the pending result keys but this seems a bit janky. Maybe the repository could hold Future<Result>
objects?