Giriş
Şu satırı dahil
ederiz.
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
Kullanım
Şöyle
yaparız. Burada CacheLoader'ın null döndürebileceği kontrol edilmiyor. Normalde etmek lazım.
LoadingCache<String, Plan> something =
CacheBuilder.newBuilder()
.concurrencyLevel(10)
.maximumSize(1000) // Maximum of 1000 records can be cached
.expireAfterWrite(60, TimeUnit.MINUTES) // Cache will expire after 60 minutes
.build(new CacheLoader<String, Plan>() { // Build the CacheLoader
@Override
public Plan load(String key) throws Exception{
Plan record = getGraphFromDB(key);
return record;
}
});
asyncReloading metodu
Bir Executor tarafından çalıştırılan reload() metodunu kolayca tanımlamayı sağlar.
Örnek
Şöyle
yaparız.
LoadingCache<String, Graph> cache1 = CacheBuilder.newBuilder()
.refreshAfterWrite(15, TimeUnit.MINUTES)
.build(CacheLoader.asyncReloading(CacheLoader.from(this::getGraphFromDB),
Executors.newSingleThreadExecutor()));
Örnek
Şöyle
yaparız
LoadingCache<String, Graph> loadingCacheSuccint = CacheBuilder.newBuilder()
.refreshAfterWrite(15, TimeUnit.MINUTES)
.recordStats()
.build(CacheLoader.asyncReloading(CacheLoader.from(this::getGraphFromDB),
Executors.newSingleThreadExecutor())
);
load metodu
İmzası
şöyle.
public V load(K key);
Açıklaması
şöyle. Yani null dönemez
Returns:
the value associated with key; must not be null
Throws:
Exception - if unable to load the result
Eğer load işlemi null dönerse exception fırlatmak gerekir. Şöyle
yaparız
new CacheLoader<ObjectId, User>() {
@Override
public User load(ObjectId k) throws Exception {
User u = DataLoader.datastore.find(User.class).field("_id").equal(k).get();
if (u != null) {
return u;
} else {
throw new UserNotFoundException();
}
}
}
LoadingCache sınıfının getUnchecked() metodu çağrılınca tetiklenir. Şöyle
yaparız.
String v = myCache.getUnchecked(key);
Örnek
Şöyle
yaparız.
new CacheLoader<String, Graph>() {
@Override
public Graph load(String key) {
return ...;
}
...
});
Örnek
new CacheLoader<Long, String>() {
public String load(Long key) {
System.out.println("load() " + key);
return "INITIAL";
}
...
});
loadAll metodu
İmzası
şöyle.
public Map<K, V> loadAll(Iterable<? extends K> ids);
LoadingCache sınıfının getAll() metodu çağrılınca
tetiklenir.
Örnek
Şöyle
yaparız.
this.cache = CacheBuilder.newBuilder().maximumSize(1000).build(
new CacheLoader<String, NamedEntity>() {
@Override
public Map<String, NamedEntity> loadAll(Iterable<? extends String> keys)
throws Exception {
Map<String, NamedEntity> map = new ConcurrentHashMap<>();
...
return map;
}
});
try {
entities = cache.getAll(keys);
} catch (Exception e) {
e.printStackTrace();
}
reload metodu
Açıklaması
şöyle.
CacheLoader.reload() takes a key and old value and returns a ListenableFuture.
Eğer bu metodu override etmezsek load() metodunu çağırır.Açıklaması
şöyle.
... default implementation calls load() synchronously,
LoadingCache sınıfının refresh() metodu çağrılınca tetiklenir. Şöyle
yaparız.
myCache.refresh(key);
Örnek - asenkron çalışma
Şöyle
yaparız. Burada işi kendi ExecutorService nesnemize havale ediyoruz
LoadingCache<String, Graph> cache = CacheBuilder.newBuilder()
.refreshAfterWrite(2, TimeUnit.MINUTES)
.recordStats()
.build(new CacheLoader<String, Graph>() {
@Override
public Graph load(String key) {
return ...;
}
public ListenableFuture<Graph> reload(final String key, Graph prev) {
ListenableFutureTask<Graph> task = ListenableFutureTask.create(
new Callable<Graph>() {
public Graph call() {
Graph graph = ...
...
return graph;
}
});
executor.execute(task);
return task;
}
});
Örnek - asenkron çalışma
Şöyle
yaparız. Burada işi kendi ExecutorService nesnemize havale ediyoruz
new CacheLoader<Long, String>() {
ExecutorService executor = Executors.newFixedThreadPool(10);
public ListenableFuture<String> reload(final Long key, String prevString) {
// asynchronous!
ListenableFutureTask<String> task = ListenableFutureTask.create(() -> {
...
return "Calculated value for " + key;
});
executor.execute(task);
return task;
}
});
Örnek
Şöyle
yaparız. Burada kendi ExecutorService sınıfımız yerine redis kullanılıyor.
@Override
public ListenableFuture<Object> reload(RedisKey<?> key, Object oldValue)
throws Exception {
CompletionStage<byte[]> f = redisClusterClient.asyncGet(key.getActualKey())
.asCompletionStage();
ListenableFutureTask<Object> task = ListenableFutureTask.create(
() -> f.toCompletableFuture().get());
f.thenRun(task::run);
return task;
}
Açıklaması
şöyle.
My RedisClient has a asyncGet() function, so I wanted to utilize it instead of maintaining a executorservice of my own and submitting it a ListenableFutureTask