Search code examples
javaconcurrencyconcurrenthashmap

Is there a standard solution in Java for concurrent value set exactly once?


I need a structure allowing to set a value at most once concurrently.
Something that has methods similar to putIfAbsent and computeIfAbsent of ConcurrentHashMap.

interface MyContainer<T>{
  void putIfAbsent(T value);

  void computeIfAbsent(Supplier<T> supp);

  Optional<T> maybeValue();
}    

// this implementation just shows intention
class DumbContainerImpl<T> implements MyContainer<T>{
  String key = "ONLYONE";
  ConcurrentHashMap map = new ConcurrentHashMap<String, T>(1);
    
  void putIfAbsent(T value){
    map.putIfAbsent(key, value);
  }

  void computeIfAbsent(Supplier<T> supp){
    map.computeIfAbsent(key, k -> supp.get());
  }

  Optional<T> maybeValue(){     
    return Optional.ofNullable(map.get(key))
  }
}

Is there something similar in a standard Java library? (any JDK version)


Solution

  • An AtomicReference can be used, with its compareAndSet() method.

    class AtomicContainer<T> implements MyContainer<T> {
        private final AtomicReference<T> ref = new AtomicReference<>();
    
        @Override
        public boolean putIfAbsent(T value) {
            if (value == null)
                throw new NullPointerException();
            return this.ref.compareAndSet(null, value);
        }
    
        @Override
        public boolean computeIfAbsent(Supplier<T> supp) {
            if (this.ref.get() == null)
                return putIfAbsent(supp.get());
            return false;
        }
    
        @Override
        public Optional<T> maybeValue() {
            return Optional.ofNullable(this.ref.get());
        }
    
    }
    
    interface MyContainer<T> {
    
        /**
         * @return true if the given value was assigned, false if a value was already assigned
         */
        boolean putIfAbsent(T value);
    
        /**
         * @return true if a value from the given supplier was assigned, false if a value was already assigned
         */
        boolean computeIfAbsent(Supplier<T> supp);
    
        Optional<T> maybeValue();
    
    }