2017-01-16 3 views
3

여러 스레드의 데이터 구조에 항목을 채우고 특정 크기에 도달 한 후에 오래된 레코드를 삭제하기 시작하는 유스 케이스가 있습니다. 그래서 이것을 위해 Guava Loading Cache를 사용하기로 결정했습니다.Loading Cache 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

'addToCache' 메소드에서'DataBuilder'를 사용할 수있게되어서 제 질문이 생겼습니다. 어떻게 그것을 사용하여 LoadingCache를 채울 수 있습니까? 그게 내 혼란이야. –

답변

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에, 당신은 당신의 캐시가 cache.get(myKey) 또는 cache.getUnchecked(myKey)를 호출하는 스레드 장면 뒤에 채워집니다 명시 적으로 더 이상 put를 호출 할 필요가 없습니다. 수동으로 캐시를 채울하려면

, 당신은 단순히 다음 같은 Cache처럼 put(K key, V value) 방법을 사용할 수 있습니다 : 당신은 캐시에게 자신을 채울하려는 경우, 당신은 CacheLoader 필요하지 않습니다

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

, Cache 인스턴스를 만들려면 build(CacheLoader<? super K1,V1> loader) 대신 build()으로 전화하면됩니다 (더 이상 LoadingCache이 아님).

코드는 다음과 같다 :

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

감사합니다. 이제 나에게 분명하다. –

+0

@ NicolasFilotto 나는 또한 구아바 캐시 [여기]에 대한 질문이 있습니다 (http://stackoverflow.com/questions/41777172/how-to-empty-guava-cache-every-30-seconds-while-sending-it-to - 다른 방법). 네가 나를 도울 수 있는지보고 싶니? – john