In order to handle concurrently executions of expensive tasks, Brian Goetz provided an example of Memorizer in his book: “Java Concurrency In Practice”. The following is a slightly modified version of the class.
| 
public class
  ConcurrentResultCache<A, V> implements
  Computable<A, V> { 
      private static final Logger logger =
  LoggerFactory.getLogger(ConcurrentResultCache.class); 
      private final
  ConcurrentMap<A, Future<V>> cache = new
  ConcurrentHashMap<A, Future<V>>(); 
      private final
  Computable<A, V> c; 
      public
  ConcurrentResultCache(final Computable<A, V> c) { 
            this.c = c; 
      } 
      public V compute(final A arg) throws
  InterruptedException { 
            logger.trace("entered
  compute..."); 
            // waiting result to be
  available. intercept any CacellationException. 
            while (true) { 
                  logger.trace("before
  first get"); 
                  Future<V> f = cache.get(arg); 
                  logger.trace("after
  first get"); 
                  if (f == null) { 
                        logger.trace("f is
  null"); 
                        // Creating
  a new task wrapped in a Callable. 
                        Callable<V> eval = new Callable<V>() { 
                              public V call() throws
  InterruptedException { 
                                    return c.compute(arg); 
                              } 
                        }; 
                        FutureTask<V> ft = new
  FutureTask<V>(eval); 
                        f = cache.putIfAbsent(arg, ft); 
                        logger.trace("after
  putIfAbsent()"); 
                        if (f == null) { 
                              // if the
  task is put into the cache first time, run the task in the SAME thread. 
                              f = ft; 
                              logger.trace("before
  run()"); 
                              ft.run(); 
                        } 
                  } 
                  try { 
                        logger.trace("before
  second get"); 
                        return f.get(); 
                  } catch
  (CancellationException e) { 
                        cache.remove(arg, f); 
                  } catch
  (ExecutionException e) { 
                        throw new
  IllegalStateException("Task execution exception caught.", e); 
                  } 
            } 
      } 
      public void remove(final String key) { 
            this.cache.remove(key); 
      } 
} 
      public void remove(final String key) { 
            this.cache.remove(key); 
      } 
} | 
As an example, if a Properties need to be loaded in a high traffic
application, it could implement the Computable interface.
| 
public class
  PropertyLoader implements Computable<String, Properties> { 
      private static final Logger logger =
  LoggerFactory.getLogger(PropertyLoader.class); 
      @Override 
      public Properties
  compute(final String filePath) throws
  InterruptedException { 
            logger.trace("entered
  PropertyLoader compute()"); 
            return
  readProperties(filePath); 
      } 
      private Properties
  readProperties(final String filePath) { 
            final String propFile = System.getProperty(filePath); 
            final Properties properties = new Properties(); 
            try { 
                  properties.load(new FileReader(propFile)); 
            } catch (IOException e) { 
                  logger.error("Failed
  to load properties.", e); 
            } 
            return properties; 
      } 
} | 
The usage of the class:
| 
private static
  ConcurrentResultCache<String, Properties> propertiesCache = new ConcurrentResultCache<String,
  Properties>(new PropertyLoader()); 
public Properties
  getClientThrottlingRateMap() { 
    final Properties properties = propertiesCache.compute(propertiesLocation); 
… | 
