2017-01-16 3 views
3

Ich habe einen Anwendungsfall, wo ich Einträge in eine Datenstruktur aus mehreren Threads füllen möchte und nach dem Erreichen einer bestimmten Größe beginnen alte Datensätze löschen. Also entschied ich mich, dafür den Guava Loading Cache zu verwenden.Wie können Einträge in Lade-Cache-Guave gefüllt werden?

Ich möchte Einträge in meinen Lade-Cache aus mehreren Threads auffüllen, und ich setze Räumungsrichtlinie wie 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). 
} 

Meine addToCache Methode von mehreren Threads aufgerufen werden, um die cache zu füllen. Ich bin verwirrt, was ich tun sollte innerhalb addToCache Methode, um den Cache zu füllen und auch wie sieht meine load Methode aus?

Hier ist DataBuilder mein Builder-Muster.

+0

Wie sollten wir wissen, wie Sie Ihre Daten geladen werden soll? Und warum möchten Sie Ihren Cache vorab auffüllen, anstatt ihn langsam laden zu lassen? – shmosel

+0

Ich meine meine Frage war, seit ich 'DataBuilder' in der' addToCache' Methode zur Verfügung habe. Wie kann ich LoadingCache mit Daten füllen? Das ist meine Verwirrung. –

Antwort

7

Offensichtlich ist Ihr Problem, dass Sie nicht den Hauptzweck eines CacheLoader bekommen.

A CacheLoader wird verwendet, um automatisch den Wert eines bestimmten Schlüssels zu laden (die im Cache existiert noch nicht), wenn get(K key) oder getUnchecked(K key) in Art und Weise fordert, dass selbst wenn wir mehrere Threads versuchen, den Wert desselben zu erhalten Gleichzeitig lädt nur ein Thread den Wert und nach dem Abschluss haben alle aufrufenden Threads den gleichen Wert.

Dies ist in der Regel nützlich, wenn der zu ladende Wert einige Zeit in Anspruch nimmt, z. B. wenn es sich um einen Datenbankzugriff oder eine lange Berechnung handelt, weil die Wahrscheinlichkeit, mehrere Threads zu verwenden, umso höher ist Laden Sie gleichzeitig denselben Wert, der Ressourcen verschwendet, ohne dass ein Mechanismus dafür sorgt, dass nur ein Thread die Daten für alle aufrufenden Threads lädt.

Also lassen Sie uns sagen, dass Ihre DataBuilder Instanzen sind lange zu bauen oder Sie müssen nur sicherstellen, dass alle Threads die gleiche Instanz für einen bestimmten Schlüssel haben, würden Sie dann in der Tat eine CacheLoader und es würde so aussehen :

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

Dank der CacheLoader, haben Sie keine Notwendigkeit, put explizit mehr als Cache hinter den Kulissen Aufruf cache.get(myKey) oder cache.getUnchecked(myKey) durch die Fäden aufgefüllt werden zu nennen.

Wenn Sie manuell möchten Ihren Cache füllen, können Sie einfach die put(K key, V value) Methode wie jede Cache als nächste:

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

Wenn Sie beabsichtigen, sich um den Cache zu füllen, müssen Sie nicht ein CacheLoader benötigen, Sie können einfach build() anstelle von build(CacheLoader<? super K1,V1> loader) anrufen, um Ihre Cache Instanz zu erstellen (es wird kein LoadingCache mehr sein).

Ihr Code wäre dann:

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

Danke. Jetzt ist es mir sehr klar. –

+0

@NicolasFilotto Ich habe auch eine Frage zu Guava-Cache [hier] (http://stackoverflow.com/questions/41777172/how-to-empty-guava-cache-every-30-seconds-while-sending-it-to -eine andere Methode). Wollte sehen, ob du mir helfen kannst? – john

Verwandte Themen