I'm looking for code equivalent to the following:
ConcurrentHashMap<int, Object> map = new ConcurrentHashMap<>();
map.computeIfAbsent(key, n -> f(n));
Where f(n)
is HTTP network call and blocking for the result
Bur referring to single element held in AtomicReference<Object>
where I need to ensure f
is called only once upon even if multiple threads do the access concurrently.
I tried using compareAndSet
but this doesn't allow lambda passing.
Does updateAndGet
achieve that? Its documentation mentions
The function should be side-effect-free, since it may be re-applied when attempted updates fail due to contention among threads.
Which doesn't seem to fill the need of invoking f
only once.
CodePudding user response:
From your question, I think you want to avoid doing the HTTP request multiple times.
You could have a map of FutureTask(s) that asynchronously performs the HTTP request for you. In this way, if a thread tries to computeIfAbsent it will see the FutureTask created by another thread even if the HTTP operation is not done yet.
CodePudding user response:
You could use an AtomicBoolean
with an initial value of true
and allow each thread should call AtomicBoolean::getAndSet
with the value false
. If the return value is true
then you execute your function.
This will ensure that the call is only made once since only the first thread will succeed.