2017-01-16 9 views
3

У меня есть прецедент, когда я хочу заполнять записи в структуре данных из нескольких потоков и после достижения определенного размера начинает отбрасывать старые записи. Поэтому я решил использовать для этого загрузочный кэш Guava.Как заполнить записи в Кэширование загрузки?

Я хочу заполнить записи в свой загрузочный кэш из нескольких потоков, и я устанавливаю политику на основе выселения как Size Based Eviction.

private final ScheduledExecutorService executorService = Executors 
     .newSingleThreadScheduledExecutor(); 
    private final LoadingCache<String, DataBuilder> cache = 
     CacheBuilder.newBuilder().maximumSize(10000000) 
      .removalListener(RemovalListeners.asynchronous(new CustomListener(), executorService)) 
      .build(new CacheLoader<String, DataBuilder>() { 
      @Override 
      public DataBuilder load(String key) throws Exception { 
       // what I should do here? 
       // return 
      } 
      }); 

// this will be called from multiple threads to populate the cache 
public void addToCache(String key, DataBuilder dataBuilder) { 
    // what I should do here? 
    //cache.get(key). 
} 

Мой addToCache метод будет вызываться из нескольких потоков для заполнения cache. Я путаю то, что я должен делать внутри метода addToCache для заполнения кеша, а также как выглядит мой метод load?

Здесь DataBuilder - это мой рисунок строителя.

+0

Как мы должны знать, как вы хотите, чтобы загрузить данные? И почему вы хотите предварительно заполнить свой кеш, вместо того чтобы разрешить ему ленивую загрузку? – shmosel

+0

Я имею в виду мой вопрос, так как у меня есть 'DataBuilder', доступный в методе' addToCache'. Как я могу использовать это для заполнения LoadCache? Это мое замешательство. –

ответ

7

Очевидно, что ваша проблема заключается в том, что вы не получаете главной цели CacheLoader.

CacheLoader используется для автоматической загрузки значение данного ключа (который не существует в кэше еще) при вызове get(K key) или getUnchecked(K key) в пути, что даже если у нас есть несколько потоков пытаются получить значение одного и того же в то же время, только один поток фактически загрузит значение и один раз выполнит все вызовы, которые будут иметь одинаковое значение.

Это обычно полезно, когда значение для загрузки занимает некоторое время, например, когда это результат доступа к базе данных или длинное вычисление, поскольку чем дольше это требуется, тем выше вероятность того, что несколько потоков будут пытаться одновременно загружать одно и то же значение, которое будет направлять ресурсы без механизма, который гарантирует, что только один поток будет загружать данные для всех вызывающих потоков.

Итак, предположим, что ваши экземпляры DataBuilder долго строились или вам просто нужно убедиться, что все потоки будут иметь один и тот же экземпляр для заданного ключа, тогда вам действительно понадобится CacheLoader, и это будет выглядеть так :

new CacheLoader<String, DataBuilder>() { 
    @Override 
    public DataBuilder load(String key) throws Exception { 
     return callSomeMethodToBuildItFromTheKey(key); // could be new DataBuilder(key) 
    } 
} 

Благодаря CacheLoader, у вас нет необходимости вызывать put явно больше, как кэш будет заполняться за сценой нитями, призывающих cache.get(myKey) или cache.getUnchecked(myKey).

Если вы хотите вручную заполнить кэш, вы можете просто использовать метод put(K key, V value) как любой Cache в следующем:

public void addToCache(String key, DataBuilder dataBuilder) { 
    cache.put(key, dataBuilder); 
} 

Если вы собираетесь заполнить кэш самостоятельно, вам не нужен CacheLoader, вы можете просто позвонить build() вместо build(CacheLoader<? super K1,V1> loader), чтобы создать свой экземпляр Cache (он больше не будет LoadingCache).

Ваш код будет таким:

private final Cache<String, DataBuilder> cache = 
     CacheBuilder.newBuilder().maximumSize(10000000) 
      .removalListener(
       RemovalListeners.asynchronous(new CustomListener(), executorService) 
     ).build(); 
+1

Спасибо. Теперь мне это очень ясно. –

+0

@NicolasFilotto У меня также есть вопрос о кеше guava [здесь] (http://stackoverflow.com/questions/41777172/how-to-empty-guava-cache-every-30-seconds-while-sending-it-to метод-свой-). Хотел посмотреть, сможешь ли ты мне помочь? – john