My requirements were:
- Bounded cache -- the number of maximum entries is bounded.
- LRU cache -- eviction is done to the Least Recently Used item first.
- Low Memory footprint -- since each entry can consume unbounded amounts of memory the cache should holds its values using WeakReference, this makes it possible for the cache to evict elements even when the cache is not full when memory is short.
- Minimized locking -- the cache should not be locked when an entry is searched, only the searched entry can be locked.
- Minimized computation -- in case of multiple threads searching for the same key, the computation of the value should be done only once.
The Compute interface is very similar to Java Callable interface. The only difference is that each call to compute receives the key and returns its value.
The Cache constructor receives 3 parameters:
- A Compute instance -- computes the values for objects that are not in the cache.
- An ExecutorService -- executes the computation of missing values (the call to compute)
- The size of the LRU cache -- the maximum number of entries that can be kept in this cache.
The cache itself built using 3 building blocks provided by Java:
- LinkedHashMap -- Hash table and linked list implementation of the Map interface, with predictable iteration order.
- Future -- an interface that represents the result of an asynchronous computation.
- And SoftReference -- which are cleared at the discretion of the garbage collector in response to memory demand.
Here is the code of SoftValue:
One more Interface the cache is using is the ExceptionStrategy, it is used to decide what to do when the call to compute(key) throws an Exception, the 2 options is to keep the mapping
Here is the source of ExceptionStrategy:
When a call to compute results in Exception the cache invoke it's instance of ExceptionStrategy removeEntry method with the key and the Exception, if removeEnty returns false the pair is kept in the cache, otherwise it does not and the next call to cache.get(key) will try to compute the value for key again.
For example the function alwaysRetain, a factory method that returns an ExceptionStrategy that always keep the mapping of an Exception in the cache can be define as:
The important part is the definition of the internal map on line 5, the map is defined as mapping from the key to a SoftValue that holds the key and a Future of the value, possibly an un-computed value.
We used the LinkedHashMap constructor that specify the accessOrder of the map as true so that get(key) will mark key as recently used as well as put(key).
The removeEldestEntry is called on each put. its result determines if the eldest entry should be removed from the map or not.
Neutrally the most used method of the cache is the get method, we'll now go over it's code:
We can see in line 5 the usage of exceptionStrategy to decide how to deal with exceptions.
The method getTask(key) in line 3 returns a Future to the computation of this entry and the computation itself is done only at the call to get() (last call in line 3).
Here is the code for getTask:
Since getTask only returns Future of the value (it does not compute the value) it can be synchronized because it's execution time is not related to the compute execution time.
On line 2 we see a call to processQueue this method removes from the map all the entries that their value was collected by the GC. we will have a look at it in short time.
On line 2 we see a call to processQueue this method removes from the map all the entries that their value was collected by the GC. we will have a look at it in short time.
Next the Future for the key is searched in the map and in case it is there it is returned (line 8), in case there is no Future for this key a new one is created by submitting a computation to the ExecutorService (line 11), the new Future is then wrapped with SoftValue to enable the gc to reclaim this value in case of memory shortage, inserted into the map and returned as the result.
It is important to notice that in this case the compute was not called yet, it will be called only when the Future's get method will be first invoked.
The usage of ExecutorService in this case give us the flexibility to control the number of threads that will be used to compute values at any given time.
For example by passing Executors.newFixThreadPoolExecutor(2) to the Cache we limit the number of concurrent calls to compute to 2, note that if we wish to call the compute on the user thread we need to write our own DirectExcutorService.
Next we will look at the processQueue method:
This method is looping over the entries that were reclaim by the GC and remove them from the map.
Great tips and very easy to understand, Thank you. bill of sale form
ReplyDeletemuş evden eve nakliyat
ReplyDeleteçanakkale evden eve nakliyat
uşak evden eve nakliyat
ardahan evden eve nakliyat
eskişehir evden eve nakliyat
NWBVİP
muş evden eve nakliyat
ReplyDeleteçanakkale evden eve nakliyat
uşak evden eve nakliyat
ardahan evden eve nakliyat
eskişehir evden eve nakliyat
8VUAE
27D8C
ReplyDeleteMardin Şehirler Arası Nakliyat
Probit Güvenilir mi
Bonk Coin Hangi Borsada
Chat Gpt Coin Hangi Borsada
Bitlis Şehir İçi Nakliyat
Çerkezköy Oto Elektrik
Balıkesir Şehirler Arası Nakliyat
Malatya Şehirler Arası Nakliyat
Bitget Güvenilir mi
EC0C0
ReplyDeleteMamak Fayans Ustası
Tekirdağ Fayans Ustası
Ünye Mutfak Dolabı
Çerkezköy Kombi Servisi
Artvin Evden Eve Nakliyat
Çerkezköy Korkuluk
Bitcoin Nasıl Alınır
Karabük Evden Eve Nakliyat
Ağrı Evden Eve Nakliyat
0D1F6
ReplyDeleteAdıyaman Evden Eve Nakliyat
Kayseri Evden Eve Nakliyat
Diyarbakır Evden Eve Nakliyat
Tokat Evden Eve Nakliyat
Mamak Boya Ustası
Çankırı Evden Eve Nakliyat
Binance Referans Kodu
Sivas Evden Eve Nakliyat
Aksaray Evden Eve Nakliyat
C3438
ReplyDeleteamiclear
A4138
ReplyDeletekırıkkale canlı görüntülü sohbet uygulamaları
maraş chat sohbet
siirt rastgele sohbet
erzincan sesli sohbet odası
erzurum ücretsiz sohbet uygulamaları
şırnak bedava sohbet odaları
istanbul kızlarla rastgele sohbet
sinop rastgele sohbet odaları
antalya canlı görüntülü sohbet siteleri
1A72E
ReplyDeleteprobit
bitcoin nasıl kazanılır
okex
binance referans kodu
sohbet canlı
referans kimliği
bitcoin hangi bankalarda var
gate io
bingx
649B4
ReplyDeletekucoin
kızlarla canlı sohbet
kripto telegram
papaya meyvesi
bitexen
btcturk
binance referans kimliği nedir
en güvenilir kripto borsası
binance 100 dolar
E83E7
ReplyDeleteprobit
paribu
vindax
papaya meyvesi
mexc
rastgele canlı sohbet
canlı sohbet ucretsiz
kaldıraç ne demek
bitexen
16007
ReplyDeletegate io
paribu
kripto para telegram grupları
kripto para nasıl alınır
coin nereden alınır
kraken
bybit
en düşük komisyonlu kripto borsası
huobi