Trying to design a threadsafe lru cache using a reentrant lock. Currently I don't like the tryLock in a loop approach. Any inputs on making it more optimal in terms of concurrency?
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class LRUNode {
String key;
String value;
LRUNode(String key,String value){
this.key = key;
this.value = value;
}
}
public class LRU {
Lock lock;
Map<String,LRUNode> map;
Deque<LRUNode> deque;
int capacity;
int size;
LRU(int capacity) {
this.size = 0;
this.capacity = capacity;
deque = new ArrayDeque<>();
this.map = new HashMap<>();
lock = new ReentrantLock();
}
public String get(String key){
try {
while (!lock.tryLock()) {
Thread.sleep(50);
}
if (map.containsKey(key)) {
//update deque
LRUNode lruNode = map.get(key);
System.out.println("Getting " + key + " from cache");
deque.remove(lruNode);
deque.offer(lruNode);
return lruNode.value;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return null;
}
public void print(){
System.out.println("----- cache contents -------");
for(Map.Entry<String,LRUNode> entry : this.map.entrySet()){
System.out.println(entry.getKey()+ " : "+ entry.getValue().value);
}
System.out.println("----------------------------");
}
public void put(String key, String value){
try {
while (!lock.tryLock()) {
Thread.sleep(50);
}
if (size == capacity) {
LRUNode nodeToBeRemoved = deque.getFirst();
System.out.println("Evicting " + nodeToBeRemoved.key + " from cache");
map.remove(nodeToBeRemoved.key);
deque.removeFirst();
size--;
}
LRUNode lruNode = new LRUNode(key, value);
map.put(key, lruNode);
deque.offer(lruNode);
System.out.println("Added " + key + " to cache");
size++;
}catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
LRU lru = new LRU(3);
lru.put("k1","v1");
lru.put("k2","v2");
lru.put("k3","v3");
lru.print();
lru.put("k4","v4");
lru.put("k5","v5");
lru.put("k6","v6");
lru.put("k7","v7");
lru.put("k8","v8");
lru.put("k9","v9");
lru.print();
}
}