title: Guava cache - How do I loadAll on any miss?
body: <p>I have a use case where the method to load my cache's data is a bulk call, but I'm never going to use getAll to get data from the cache.  Is there a way to have multiple concurrent gets all block on a single loadAll?  I don't want individual gets on different keys to result in multiple calls to the data source.</p>
  
  <pre><code>cache.get(key1); // missing entry, starts refresh
  cache.get(key2); // separate thread, already getting reloaded due to key1 miss
  </code></pre>
  
  <p>I think I'll have to implement my own synchronization after looking into the LocalCache, using something like a local cache in my data accessor that only allows a call through every so many units of time. When a call does go through, update the local copy with a single assignment statement.</p>
  
  <p>Am I missing something from Guava's cache library?</p>
  
  <p><strong>Edit:</strong></p>
  
  <p>I'm considering something like the following.  However, it could potentially continue returning stale data while <code>loadAll</code> finishes.  I'd prefer everything blocks at <code>load</code>, and only the first request causes <code>loadAll</code> to proceed.</p>
  
  <pre><code>public class DataCacheLoader extends CacheLoader&lt;String, Double&gt;
  {
      private final Cache&lt;String, Double&gt; cache;
      private ConcurrentMap&lt;String, Double&gt; currentData;
      private final AtomicBoolean isloading;
  
      public DataCacheLoader( final Cache&lt;String, Double&gt; cache )
      {
          this.cache = cache;
          isLoading = new AtomicBoolean( false );
      }
  
      @Override
      public Double load( final String key ) throws Exception
      {
          if ( isLoading.compareAndSet( false, true ) )
          {
              cache.putAll( loadAll( Lists.newArrayList( key ) ) ) );
          }
          return currentData.get( key );
      }
  
      @Override
      public Map&lt;String, Double&gt; loadAll(Iterable&lt;? extends String&gt; keys) throws Exception
      {
          currentData = source.getAllData();
          return currentData;
      }
  }
  </code></pre>